@linyjs/plugin-docs 0.1.2 → 0.1.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/README.md CHANGED
@@ -74,7 +74,8 @@ docs/
74
74
  │ ├── client-module.md # 客户端模块
75
75
  │ ├── ui-slots.md # UI扩展插槽
76
76
  │ ├── permissions.md # 权限管理
77
- └── data-persistence.md # 数据持久化
77
+ ├── data-persistence.md # 数据持久化
78
+ │ └── authentication.md # 用户认证
78
79
  ├── api-reference/ # API参考
79
80
  │ ├── server-interface.md
80
81
  │ ├── client-interface.md
@@ -102,12 +103,40 @@ examples/
102
103
  - 详细的 README 说明
103
104
  - 可直接打包为 .mpk 文件
104
105
 
106
+ ## 🔧 核心模块
107
+
108
+ linyjs 提供了以下核心模块,插件可以通过依赖注入方式调用这些基础服务:
109
+
110
+ ### @linyjs/mongodb
111
+ **MongoDB 数据库服务**
112
+ - 提供数据持久化存储
113
+ - 支持 CRUD 操作和复杂查询
114
+ - 详情:[数据持久化指南](./docs/guides/data-persistence.md)
115
+
116
+ ### @linyjs/auth
117
+ **用户认证系统**
118
+ - 支持用户注册、登录、Token 验证
119
+ - 提供 JWT 身份验证
120
+ - 详情:[认证指南](./docs/guides/authentication.md)
121
+
122
+ ### @linyjs/permission
123
+ **权限管理系统**
124
+ - 基于角色的访问控制(RBAC)
125
+ - 细粒度的权限定义
126
+ - 详情:[权限管理指南](./docs/guides/permissions.md)
127
+
105
128
  ## 🔗 相关链接
106
129
 
107
130
  - [linyjs 框架](https://github.com/linyjs/linyjs)
108
131
  - [CLI 工具文档](https://github.com/linyjs/linyjs/tree/main/packages/cli)
109
132
  - [报告文档问题](https://github.com/linyjs/linyjs/issues)
110
133
 
134
+ ## 📖 核心模块指南
135
+
136
+ - 💾 [数据持久化](./docs/guides/data-persistence.md) - 使用 @linyjs/mongodb
137
+ - 🔐 [用户认证](./docs/guides/authentication.md) - 使用 @linyjs/auth
138
+ - 🛡️ [权限管理](./docs/guides/permissions.md) - 使用 @linyjs/permission
139
+
111
140
  ## 📄 许可证
112
141
 
113
142
  MIT License
@@ -330,11 +330,31 @@ registry.register({
330
330
 
331
331
  ---
332
332
 
333
+ ## 基础模块
334
+
335
+ linyjs 框架提供了以下基础模块,插件开发者可以通过依赖注入方式使用:
336
+
337
+ ### 数据库模块
338
+ - **@linyjs/mongodb** - MongoDB 数据库服务
339
+ - 提供数据库连接、CRUD 操作、索引管理等功能
340
+ - 详见:[数据持久化指南](../guides/data-persistence.md)
341
+
342
+ ### 认证模块
343
+ - **@linyjs/auth** - 用户认证系统
344
+ - 提供用户注册、登录、Token 验证等功能
345
+ - 详见:[认证指南](../guides/authentication.md)
346
+
347
+ ### 权限模块
348
+ - **@linyjs/permission** - 权限管理系统
349
+ - 提供基于角色的访问控制(RBAC)
350
+ - 详见:[权限管理指南](../guides/permissions.md)
351
+
333
352
  ## 相关文档
334
353
 
335
354
  - 📖 [服务端模块开发](../guides/server-module.md)
336
355
  - 💻 [客户端模块开发](../guides/client-module.md)
337
356
  - 🎨 [UI 扩展插槽](../guides/ui-slots.md)
357
+ - 💾 [基础模块使用指南](../README.md#-核心模块)
338
358
 
339
359
  ---
340
360
 
@@ -0,0 +1,420 @@
1
+ # 用户认证
2
+
3
+ 本指南介绍如何在 linyjs 插件中使用认证系统实现用户登录、注册和权限验证。
4
+
5
+ ## 概述
6
+
7
+ linyjs 提供完整的用户认证系统,支持:
8
+
9
+ - 🔐 用户注册和登录
10
+ - 🪙 JWT Token 认证
11
+ - 🛡️ 路由级别的认证保护
12
+ - 👤 用户信息管理
13
+
14
+ ## 配置认证服务
15
+
16
+ ### 在服务端模块中注入依赖
17
+
18
+ ```typescript
19
+ import type { IModule } from '@linyjs/server-module-interface';
20
+ import { login, register, verifyToken } from '@linyjs/auth';
21
+
22
+ export const myServerModule: IModule = {
23
+ name: 'myServer',
24
+ moduleDependencies: ['auth'], // 依赖认证模块
25
+ serviceDefs: [
26
+ {
27
+ serviceTag: 'authController',
28
+ serviceImpl: AuthController,
29
+ dependencies: [], // 依赖注入将在类构造函数中使用
30
+ meta: { usageType: 'controller' }
31
+ }
32
+ ]
33
+ };
34
+ ```
35
+
36
+ ## 基本认证操作
37
+
38
+ ### 用户注册
39
+
40
+ ```typescript
41
+ import { register } from '@linyjs/auth';
42
+
43
+ class AuthController {
44
+ getRoutes() {
45
+ return [{
46
+ method: 'POST' as const,
47
+ path: '/api/auth/register',
48
+ middlewares: [],
49
+ responseType: 'json' as const,
50
+ handler: async (req: any) => {
51
+ const { username, email, password } = req.body;
52
+
53
+ try {
54
+ const result = await register(username, email, password);
55
+ return {
56
+ success: true,
57
+ message: 'Registration successful',
58
+ data: result
59
+ };
60
+ } catch (error) {
61
+ return {
62
+ success: false,
63
+ message: error instanceof Error ? error.message : 'Registration failed'
64
+ };
65
+ }
66
+ }
67
+ }];
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### 用户登录
73
+
74
+ ```typescript
75
+ import { login } from '@linyjs/auth';
76
+
77
+ class AuthController {
78
+ getRoutes() {
79
+ return [{
80
+ method: 'POST' as const,
81
+ path: '/api/auth/login',
82
+ middlewares: [],
83
+ responseType: 'json' as const,
84
+ handler: async (req: any) => {
85
+ const { identifier, password } = req.body;
86
+
87
+ try {
88
+ const result = await login(identifier, password);
89
+ return {
90
+ success: true,
91
+ message: 'Login successful',
92
+ data: result
93
+ };
94
+ } catch (error) {
95
+ return {
96
+ success: false,
97
+ message: error instanceof Error ? error.message : 'Login failed'
98
+ };
99
+ }
100
+ }
101
+ }];
102
+ }
103
+ }
104
+ ```
105
+
106
+ ### Token 验证
107
+
108
+ ```typescript
109
+ import { verifyToken, getUserById } from '@linyjs/auth';
110
+
111
+ class AuthController {
112
+ getRoutes() {
113
+ return [{
114
+ method: 'GET' as const,
115
+ path: '/api/auth/me',
116
+ middlewares: [],
117
+ responseType: 'json' as const,
118
+ handler: async (req: any) => {
119
+ const token = req.headers.authorization?.replace('Bearer ', '');
120
+
121
+ if (!token) {
122
+ return {
123
+ success: false,
124
+ message: 'No token provided'
125
+ };
126
+ }
127
+
128
+ try {
129
+ const payload = await verifyToken(token);
130
+ const user = await getUserById(payload.userId);
131
+
132
+ return {
133
+ success: true,
134
+ data: user
135
+ };
136
+ } catch (error) {
137
+ return {
138
+ success: false,
139
+ message: 'Invalid token'
140
+ };
141
+ }
142
+ }
143
+ }];
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## 认证中间件
149
+
150
+ ### 创建认证中间件
151
+
152
+ ```typescript
153
+ import { verifyToken, getUserById } from '@linyjs/auth';
154
+
155
+ async function authMiddleware(req: any, res: any, next: any) {
156
+ const token = req.headers.authorization?.replace('Bearer ', '');
157
+
158
+ if (!token) {
159
+ return res.status(401).json({
160
+ success: false,
161
+ message: 'Authentication token required'
162
+ });
163
+ }
164
+
165
+ try {
166
+ const payload = await verifyToken(token);
167
+ const user = await getUserById(payload.userId);
168
+
169
+ if (!user) {
170
+ return res.status(401).json({
171
+ success: false,
172
+ message: 'User not found'
173
+ });
174
+ }
175
+
176
+ // 将用户信息添加到请求对象
177
+ req.user = user;
178
+ req.userId = user._id;
179
+
180
+ next();
181
+ } catch (error) {
182
+ return res.status(401).json({
183
+ success: false,
184
+ message: 'Invalid authentication token'
185
+ });
186
+ }
187
+ }
188
+ ```
189
+
190
+ ### 使用认证中间件
191
+
192
+ ```typescript
193
+ class ProtectedController {
194
+ getRoutes() {
195
+ return [{
196
+ method: 'GET' as const,
197
+ path: '/api/protected',
198
+ middlewares: [authMiddleware], // 使用认证中间件
199
+ responseType: 'json' as const,
200
+ handler: async (req: any) => {
201
+ return {
202
+ success: true,
203
+ message: `Hello ${req.user.username}! You have access to this protected route.`
204
+ };
205
+ }
206
+ }];
207
+ }
208
+ }
209
+ ```
210
+
211
+ ## 客户端认证
212
+
213
+ ### 登录表单示例
214
+
215
+ ```typescript
216
+ import type { IModule } from '@linyjs/client-module-interface';
217
+ import React, { useState } from 'react';
218
+
219
+ function LoginForm() {
220
+ const [formData, setFormData] = useState({
221
+ identifier: '',
222
+ password: ''
223
+ });
224
+ const [error, setError] = useState('');
225
+
226
+ const handleSubmit = async (e: React.FormEvent) => {
227
+ e.preventDefault();
228
+
229
+ try {
230
+ const response = await fetch('/api/auth/login', {
231
+ method: 'POST',
232
+ headers: {
233
+ 'Content-Type': 'application/json'
234
+ },
235
+ body: JSON.stringify(formData)
236
+ });
237
+
238
+ const result = await response.json();
239
+
240
+ if (result.success) {
241
+ // 保存 token 到 localStorage 或 cookie
242
+ localStorage.setItem('token', result.data.token);
243
+ // 跳转或刷新页面
244
+ window.location.reload();
245
+ } else {
246
+ setError(result.message);
247
+ }
248
+ } catch (err) {
249
+ setError('Network error');
250
+ }
251
+ };
252
+
253
+ return (
254
+ <form onSubmit={handleSubmit}>
255
+ <div>
256
+ <label>用户名或邮箱:</label>
257
+ <input
258
+ type="text"
259
+ value={formData.identifier}
260
+ onChange={(e) => setFormData({ ...formData, identifier: e.target.value })}
261
+ required
262
+ />
263
+ </div>
264
+ <div>
265
+ <label>密码:</label>
266
+ <input
267
+ type="password"
268
+ value={formData.password}
269
+ onChange={(e) => setFormData({ ...formData, password: e.target.value })}
270
+ required
271
+ />
272
+ </div>
273
+ {error && <div className="error">{error}</div>}
274
+ <button type="submit">登录</button>
275
+ </form>
276
+ );
277
+ }
278
+
279
+ export const authClientModule: IModule = {
280
+ name: 'authClient',
281
+ serviceDefs: [{
282
+ serviceTag: 'loginForm',
283
+ serviceImpl: function() {
284
+ getComponents() {
285
+ return {
286
+ LoginForm: {
287
+ component: LoginForm,
288
+ meta: { usageType: 'normal_component' }
289
+ }
290
+ };
291
+ }
292
+ },
293
+ meta: { usageType: 'normal_service' }
294
+ }]
295
+ };
296
+ ```
297
+
298
+ ## 认证状态管理
299
+
300
+ ### 创建认证 Hook
301
+
302
+ ```typescript
303
+ import { useState, useEffect } from 'react';
304
+
305
+ interface User {
306
+ _id: string;
307
+ username: string;
308
+ email: string;
309
+ createdAt: Date;
310
+ roles?: string[];
311
+ }
312
+
313
+ export function useAuth() {
314
+ const [user, setUser] = useState<User | null>(null);
315
+ const [loading, setLoading] = useState(true);
316
+
317
+ useEffect(() => {
318
+ const token = localStorage.getItem('token');
319
+
320
+ if (!token) {
321
+ setLoading(false);
322
+ return;
323
+ }
324
+
325
+ fetch('/api/auth/me', {
326
+ headers: {
327
+ 'Authorization': `Bearer ${token}`
328
+ }
329
+ })
330
+ .then(response => response.json())
331
+ .then(result => {
332
+ if (result.success) {
333
+ setUser(result.data);
334
+ } else {
335
+ localStorage.removeItem('token');
336
+ }
337
+ })
338
+ .finally(() => {
339
+ setLoading(false);
340
+ });
341
+ }, []);
342
+
343
+ const login = async (identifier: string, password: string) => {
344
+ const response = await fetch('/api/auth/login', {
345
+ method: 'POST',
346
+ headers: {
347
+ 'Content-Type': 'application/json'
348
+ },
349
+ body: JSON.stringify({ identifier, password })
350
+ });
351
+
352
+ const result = await response.json();
353
+
354
+ if (result.success) {
355
+ localStorage.setItem('token', result.data.token);
356
+ setUser(result.data.user);
357
+ return true;
358
+ }
359
+
360
+ return false;
361
+ };
362
+
363
+ const logout = () => {
364
+ localStorage.removeItem('token');
365
+ setUser(null);
366
+ };
367
+
368
+ const isAuthenticated = !!user;
369
+
370
+ return {
371
+ user,
372
+ loading,
373
+ isAuthenticated,
374
+ login,
375
+ logout
376
+ };
377
+ }
378
+ ```
379
+
380
+ ## 最佳实践
381
+
382
+ ### 1. Token 存储
383
+ - 使用 `localStorage` 或 `cookie` 存储 token
384
+ - 考虑安全性时优先使用 `httpOnly` cookie
385
+ - 实现 token 自动刷新机制
386
+
387
+ ### 2. 错误处理
388
+ - 捕获并处理认证相关的错误
389
+ - 提供用户友好的错误消息
390
+ - 记录详细的错误日志用于调试
391
+
392
+ ### 3. 安全性
393
+ - 始终在服务端验证 token
394
+ - 不要在客户端存储敏感信息
395
+ - 使用强密码策略
396
+ - 考虑实现两步验证增强安全性
397
+
398
+ ### 4. 用户体验
399
+ - 记住用户的登录状态
400
+ - 自动续期 token 避免频繁登录
401
+ - 在 token 过期时友好提示用户
402
+
403
+ ## 故障排除
404
+
405
+ ### 常见问题
406
+
407
+ 1. **Token 无法验证**
408
+ - 检查 JWT_SECRET 是否正确配置
409
+ - 确认 token 未过期
410
+ - 验证 token 格式是否正确
411
+
412
+ 2. **用户无法登录**
413
+ - 检查用户名/邮箱和密码是否正确
414
+ - 确认用户账户已激活
415
+ - 检查数据库连接是否正常
416
+
417
+ 3. **中间件无法获取用户信息**
418
+ - 确认 token 在请求头中正确传递
419
+ - 检查 verifyToken 函数是否正常工作
420
+ - 验证 getUserById 是否能找到对应用户
@@ -306,6 +306,9 @@ npx @linyjs/cli validate *.mpk
306
306
  - 🔧 [API 参考](../../docs/api-reference/server-interface.md)
307
307
  - 📚 [服务端模块指南](../../docs/guides/server-module.md)
308
308
  - 🎨 [客户端模块指南](../../docs/guides/client-module.md)
309
+ - 💾 [数据持久化](../../docs/guides/data-persistence.md) - 使用 MongoDB 模块
310
+ - 🔐 [用户认证](../../docs/guides/authentication.md) - 使用 Auth 模块
311
+ - 🛡️ [权限管理](../../docs/guides/permissions.md) - 使用 Permission 模块
309
312
 
310
313
  ## 许可证
311
314
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linyjs/plugin-docs",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Plugin development documentation and examples for linyjs framework",
5
5
  "keywords": [
6
6
  "linyjs",