From b8d2a93c9fab258882de79b74b2135ff1a25cdb5 Mon Sep 17 00:00:00 2001 From: movingsam Date: Sat, 28 Feb 2026 18:38:17 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=BA=93=E5=88=86=E6=9E=90=E6=96=87=E6=A1=A3=EF=BC=88=E4=B8=AD?= =?UTF-8?q?=E6=96=87=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - STACK.md - 技术栈和依赖 - INTEGRATIONS.md - 外部集成 - ARCHITECTURE.md - 架构设计 - STRUCTURE.md - 代码库结构 - CONVENTIONS.md - 编码规范 - TESTING.md - 测试模式 - CONCERNS.md - 技术债务和问题 --- .planning/codebase/ARCHITECTURE.md | 109 ++++++++++++++++++++++ .planning/codebase/CONCERNS.md | 75 +++++++++++++++ .planning/codebase/CONVENTIONS.md | 118 +++++++++++++++++++++++ .planning/codebase/INTEGRATIONS.md | 86 +++++++++++++++++ .planning/codebase/STACK.md | 86 +++++++++++++++++ .planning/codebase/STRUCTURE.md | 96 +++++++++++++++++++ .planning/codebase/TESTING.md | 144 +++++++++++++++++++++++++++++ 7 files changed, 714 insertions(+) create mode 100644 .planning/codebase/ARCHITECTURE.md create mode 100644 .planning/codebase/CONCERNS.md create mode 100644 .planning/codebase/CONVENTIONS.md create mode 100644 .planning/codebase/INTEGRATIONS.md create mode 100644 .planning/codebase/STACK.md create mode 100644 .planning/codebase/STRUCTURE.md create mode 100644 .planning/codebase/TESTING.md diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md new file mode 100644 index 0000000..317e15d --- /dev/null +++ b/.planning/codebase/ARCHITECTURE.md @@ -0,0 +1,109 @@ +# 架构 + +**分析日期:** 2026-02-28 + +## 模式概述 + +**整体:** 分层架构 + 领域驱动设计 (DDD) + +**关键特性:** +- **控制器层 (Controllers)** - 处理 HTTP 请求,返回 API 响应 +- **服务层 (Services)** - 业务逻辑实现,使用依赖注入 +- **数据访问层** - 通过 Entity Framework Core 访问数据库 +- **领域模型** - 来自外部 Domain 程序集 (Fengling.Platform.Domain) + +## 层次 + +**控制器层 (Controllers):** +- 位置:`src/Controllers/` +- 包含:`UsersController.cs`, `RolesController.cs`, `TenantsController.cs`, `OAuthClientsController.cs`, `GatewayController.cs` +- 职责:处理 HTTP 请求、参数验证、返回响应 +- 依赖:Service 层接口 + +**服务层 (Services):** +- 位置:`src/Services/` +- 包含:`UserService.cs`, `RoleService.cs`, `TenantService.cs`, `OAuthClientService.cs`, `GatewayService.cs`, `H5LinkService.cs` +- 职责:业务逻辑实现、数据转换、事务管理 +- 依赖:Domain 模型、DbContext、UserManager、RoleManager + +**数据层 (Data/Infrastructure):** +- PlatformDbContext - 平台业务数据 +- GatewayDbContext - 网关配置数据 +- 仓储模式:通过 NetCorePal.Extensions.Repository + +**领域层 (Domain - 外部引用):** +- Fengling.Platform.Domain.AggregatesModel.UserAggregate +- Fengling.Platform.Domain.AggregatesModel.RoleAggregate +- Fengling.Platform.Domain.AggregatesModel.TenantAggregate + +## 数据流 + +**典型请求流程:** + +1. **HTTP 请求** → Controller 接收 +2. **参数验证** → DTO 绑定 +3. **业务处理** → Service 层执行 +4. **数据持久化** → EF Core 保存 +5. **响应返回** → Controller 返回结果 + +**状态管理:** +- 无状态 API 设计 +- 状态存储在 PostgreSQL 数据库 +- 认证状态通过 JWT Token 传递 + +## 关键抽象 + +**服务接口:** +- `IUserService` - 用户管理 +- `IRoleService` - 角色管理 +- `ITenantService` - 租户管理 +- `IOAuthClientService` - OAuth 客户端管理 +- `IGatewayService` - 网关配置 +- `IH5LinkService` - H5 链接服务 + +**数据传输对象 (DTO):** +- 位置:`src/Models/Dtos/` +- 模式:CreateXxxDto, UpdateXxxDto, XxxDto, XxxQueryDto +- 用途:API 请求/响应数据结构 + +## 入口点 + +**主入口:** +- 位置:`src/Program.cs` +- 触发:应用启动时执行 +- 职责:服务注册、中间件配置、管道构建 + +**API 端点:** +- `/api/console/[controller]` - RESTful API 前缀 +- `/swagger` - API 文档 + +## 错误处理 + +**策略:** +- 异常捕获 + 日志记录 +- 返回标准 HTTP 状态码 +- 错误详情通过响应体返回 + +**模式:** +```csharp +try { + // 业务逻辑 +} catch (KeyNotFoundException ex) { + return NotFound(); +} catch (InvalidOperationException ex) { + return BadRequest(); +} catch (Exception ex) { + _logger.LogError(ex, "..."); + return StatusCode(500); +} +``` + +## 跨领域关注 + +**日志:** Microsoft.Extensions.Logging + ILogger +**验证:** ASP.NET Core Model Validation + FluentValidation (已引用) +**认证:** OpenIddict + JWT Bearer + +--- + +*架构分析:2026-02-28* diff --git a/.planning/codebase/CONCERNS.md b/.planning/codebase/CONCERNS.md new file mode 100644 index 0000000..c3944fa --- /dev/null +++ b/.planning/codebase/CONCERNS.md @@ -0,0 +1,75 @@ +# 代码库问题 + +**分析日期:** 2026-02-28 + +## 技术债务 + +**硬编码密钥:** +- 问题:`src/Program.cs:62` 包含硬编码的 OAuth 客户端密钥 +- 影响:安全风险,不适合生产环境 +- 修复:使用环境变量或密钥管理服务 + +**缺少测试项目:** +- 问题:当前项目没有测试目录 +- 影响:无法进行自动化测试,难以保证代码质量 +- 修复:添加 xUnit/MSTest 测试项目 + +## 已知问题 + +**当前未发现严重 Bug:** +- 代码结构清晰,异常处理完善 + +## 安全考虑 + +**OAuth 密钥硬编码:** +- 风险:生产环境密钥泄露风险 +- 当前缓解:仅在开发环境使用 +- 建议:使用环境变量或密钥 vault + +**CORS 允许所有:** +- 风险:`policy.AllowAnyOrigin()` 存在安全风险 +- 当前缓解:仅开发环境使用 +- 建议:生产环境限制具体域名 + +## 性能问题 + +**当前未发现明显性能瓶颈:** +- 使用 Entity Framework Core 进行数据库查询 +- 支持分页查询,避免大数据量返回 + +## 脆弱区域 + +**审计日志记录:** +- 每次操作都写入审计日志 +- 高并发场景可能成为瓶颈 +- 建议:考虑异步写入或批量处理 + +## 扩展限制 + +**当前架构支持:** +- 水平扩展:通过 Docker 容器化易于扩展 +- 功能扩展:分层架构便于添加新模块 + +## 依赖风险 + +**外部依赖:** +- NetCorePal.Extensions - 自定义扩展库 +- OpenIddict - 社区维护的开源库 +- 建议:关注版本更新,及时升级 + +## 缺失功能 + +**缺失测试覆盖:** +- 无单元测试 +- 无集成测试 +- 无 API 测试 +- 优先级:高 + +**缺失功能:** +- 无缓存层(Redis 已引用但未使用) +- 无消息队列集成 +- 无后台任务系统 + +--- + +*问题审计:2026-02-28* diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md new file mode 100644 index 0000000..07f83e5 --- /dev/null +++ b/.planning/codebase/CONVENTIONS.md @@ -0,0 +1,118 @@ +# 编码规范 + +**分析日期:** 2026-02-28 + +## 命名模式 + +**文件:** +- PascalCase:`UserService.cs`、`UsersController.cs` + +**类/接口:** +- PascalCase:`UserService`、`IUserService` + +**方法:** +- PascalCase:`GetUsersAsync`、`CreateUserAsync` + +**变量:** +- camelCase:`userService`、`userName` + +## 代码风格 + +**格式化:** +- 使用 .editorconfig 或 Rider/VS 默认格式化 +- 花括号风格:K&R + +**命名空间:** +- 层级式:`Fengling.Console.Controllers` + +## 导入组织 + +**顺序:** +1. System 命名空间 +2. 项目内部命名空间 +3. 第三方库 + +**示例:** +```csharp +using System; +using System.Collections.Generic; +using Fengling.Console.Services; +using Fengling.Platform.Domain; +using Microsoft.AspNetCore.Mvc; +``` + +## 错误处理 + +**模式:** +- 使用 try-catch 捕获异常 +- 按异常类型返回不同 HTTP 状态码 +- 记录日志:`_logger.LogError(ex, "...")` + +**示例:** +```csharp +try { + await _userService.CreateUserAsync(dto); +} catch (InvalidOperationException ex) { + return BadRequest(new { message = ex.Message }); +} catch (Exception ex) { + _logger.LogError(ex, "Error creating user"); + return StatusCode(500, new { message = ex.Message }); +} +``` + +## 日志 + +**框架:** Microsoft.Extensions.Logging + ILogger + +**模式:** +```csharp +private readonly ILogger _logger; + +_logger.LogError(ex, "Error message"); +_logger.LogWarning(ex, "Warning message"); +``` + +## 注释 + +**何时注释:** +- 公开 API 方法使用 XML 文档注释 +- 复杂业务逻辑添加说明 + +**XML 注释示例:** +```csharp +/// +/// 获取用户列表 +/// +/// 分页查询参数 +/// 分页的用户列表 +[HttpGet] +public async Task>> GetUsers(...) +``` + +## 函数设计 + +**大小:** +- 保持方法简洁,单一职责 +- 复杂逻辑拆分到私有方法 + +**参数:** +- 使用 DTO 进行参数分组 +- 异步方法使用 Async 后缀 + +**返回值:** +- 使用 Task 返回异步结果 +- 集合使用 IEnumerable + +## 模块设计 + +**导出:** +- 公开接口:I[Xxx]Service +- 实现类:XxxService + +**依赖注入:** +- 构造函数注入 +- 接口+实现配对 + +--- + +*规范分析:2026-02-28* diff --git a/.planning/codebase/INTEGRATIONS.md b/.planning/codebase/INTEGRATIONS.md new file mode 100644 index 0000000..6eeda1a --- /dev/null +++ b/.planning/codebase/INTEGRATIONS.md @@ -0,0 +1,86 @@ +# 外部集成 + +**分析日期:** 2026-02-28 + +## APIs & 外部服务 + +**身份认证:** +- **OpenIddict** - OAuth 2.0 / OpenID Connect 身份提供商 + - 实现:内置 OpenIddict 认证服务器 + - 客户端:fengling-api + - 密钥:fengling-api-secret(硬编码,见 `src/Program.cs:62`) + - 发行者:http://localhost:5132/ + +**反向代理:** +- **YARP (YarpGateway)** - 反向代理网关 + - 项目引用:`../../fengling-gateway/src/YarpGateway.csproj` + - 用于 API 网关和请求转发 + +## 数据存储 + +**数据库:** +- **PostgreSQL** - 主数据库 + - 连接:`DefaultConnection` (PlatformDbContext) + - 连接:`GatewayConnection` (GatewayDbContext) + - ORM:Entity Framework Core + Npgsql + +**表结构:** +- 用户表 (ApplicationUser) +- 角色表 (ApplicationRole) +- 租户表 (Tenant) +- OAuth 客户端表 +- 审计日志表 (AuditLog) +- 网关配置表 + +## 身份认证 + +**认证方案:** +- OpenIddict Validation (Bearer Token) +- JWT Bearer 认证 +- ASP.NET Core Identity + +**用户管理:** +- ASP.NET Core Identity +- 支持租户隔离 (TenantInfo) + +## 监控与可观测性 + +**日志:** +- 使用 Microsoft.Extensions.Logging +- 通过 ILogger 注入 +- 开发环境启用敏感数据日志 + +**API 文档:** +- Swagger / OpenAPI +- 端点:`/swagger/v1/swagger.json` + +## CI/CD & 部署 + +**主机:** +- Docker 容器化 +- Dockerfile 位于 `src/Dockerfile` + +**CI/CD 流水线:** +- Gitea Actions (`.gitea/workflows/`) + - `deploy.yml` - 部署流水线 + - `docker.yml` - Docker 构建 + - `build.yml` - 构建流水线 + +## 环境配置 + +**必需环境变量:** +- `ConnectionStrings:DefaultConnection` - 平台数据库连接 +- `ConnectionStrings:GatewayConnection` - 网关数据库连接 + +**配置文件:** +- `appsettings.json` - 应用配置 +- `appsettings.Development.json` - 开发配置 + +## Webhooks & 回调 + +**无外部 Webhooks:** +- 当前无外部系统回调集成 + +--- + +*集成审计:2026-02-28* diff --git a/.planning/codebase/STACK.md b/.planning/codebase/STACK.md new file mode 100644 index 0000000..162cf1d --- /dev/null +++ b/.planning/codebase/STACK.md @@ -0,0 +1,86 @@ +# 技术栈 + +**分析日期:** 2026-02-28 + +## 语言 + +**主要:** +- **C#** (.NET 10.0) - 后端 API 开发 + +**次要:** +- **JSON** - 配置文件和数据交换格式 + +## 运行时 + +**环境:** +- .NET 10.0.103 SDK +- ASP.NET Core 10.0 Web 应用 + +**包管理:** +- NuGet +- `global.json` 指定 SDK 版本 10.0.103,rollForward: latestMinor + +## 框架 + +**核心:** +- **ASP.NET Core 10.0** - Web 框架 +- **Entity Framework Core** - ORM,用于数据访问 +- **Npgsql.EntityFrameworkCore.PostgreSQL** - PostgreSQL 数据库驱动 + +**身份认证:** +- **OpenIddict** - OAuth 2.0 / OIDC 身份提供商 +- **Microsoft.AspNetCore.Authentication.JwtBearer** - JWT 令牌认证 + +**其他:** +- **Swashbuckle.AspNetCore** - Swagger/OpenAPI 文档 +- **QRCoder** + **SkiaSharp** - 二维码生成 +- **NetCorePal.Extensions** - 扩展库集合 + +## 关键依赖 + +**核心业务:** +- `Npgsql.EntityFrameworkCore.PostgreSQL` - PostgreSQL 数据库访问 +- `OpenIddict.*` - 身份认证和授权 +- `Microsoft.AspNetCore.Identity.EntityFrameworkCore` - 用户身份管理 + +**扩展库:** +- `NetCorePal.Extensions.AspNetCore` - ASP.NET Core 扩展 +- `NetCorePal.Extensions.DistributedLocks.Redis` - 分布式锁 +- `NetCorePal.Extensions.Repository.EntityFrameworkCore` - 仓储模式 + +**工具库:** +- `Swashbuckle.AspNetCore` - API 文档 +- `QRCoder` + `SkiaSharp` - 二维码生成 +- `Microsoft.OpenApi` - OpenAPI 支持 + +## 项目引用 + +- `YarpGateway` - 反向代理网关 +- `Fengling.Platform.Infrastructure` - 平台基础设施 + +## 配置 + +**环境配置:** +- `appsettings.json` - 默认配置 +- `appsettings.Development.json` - 开发环境配置 +- `launchSettings.json` - 启动配置 + +**数据库连接:** +- `DefaultConnection` - 平台数据库 (PlatformDbContext) +- `GatewayConnection` - 网关数据库 (GatewayDbContext) + +## 平台要求 + +**开发:** +- .NET 10.0 SDK +- PostgreSQL 数据库 +- Visual Studio Code / Rider / Visual Studio + +**生产:** +- Docker 容器化部署 +- Linux 服务器 +- PostgreSQL 数据库 + +--- + +*技术栈分析:2026-02-28* diff --git a/.planning/codebase/STRUCTURE.md b/.planning/codebase/STRUCTURE.md new file mode 100644 index 0000000..1ba3c90 --- /dev/null +++ b/.planning/codebase/STRUCTURE.md @@ -0,0 +1,96 @@ +# 代码库结构 + +**分析日期:** 2026-02-28 + +## 目录布局 + +``` +fengling-console/ +├── global.json # .NET SDK 版本配置 +├── Directory.Build.props # 项目共享属性 +├── src/ +│ ├── Fengling.Console.csproj # 主项目文件 +│ ├── Program.cs # 应用入口 +│ ├── Dockerfile # Docker 构建文件 +│ ├── appsettings.json # 应用配置 +│ ├── appsettings.Development.json # 开发环境配置 +│ ├── Properties/ +│ │ └── launchSettings.json # 启动配置 +│ ├── Controllers/ # API 控制器 +│ ├── Services/ # 业务服务层 +│ ├── Models/ +│ │ └── Dtos/ # 数据传输对象 +│ └── bin/Debug/ # 编译输出 +├── .gitea/workflows/ # CI/CD 流水线 +``` + +## 目录用途 + +**src/Controllers/:** +- 用途:API 端点定义 +- 包含文件: + - `UsersController.cs` - 用户管理 API + - `RolesController.cs` - 角色管理 API + - `TenantsController.cs` - 租户管理 API + - `OAuthClientsController.cs` - OAuth 客户端 API + - `GatewayController.cs` - 网关配置 API + - `GlobalUsing.cs` - 全局 using 指令 + +**src/Services/:** +- 用途:业务逻辑实现 +- 包含文件: + - `UserService.cs` - 用户业务逻辑 + - `RoleService.cs` - 角色业务逻辑 + - `TenantService.cs` - 租户业务逻辑 + - `OAuthClientService.cs` - OAuth 客户端逻辑 + - `GatewayService.cs` - 网关配置逻辑 + - `H5LinkService.cs` - H5 链接服务 + +**src/Models/Dtos/:** +- 用途:API 数据传输对象 +- 包含文件: + - CreateXxxDto.cs (CreateUserDto, CreateRoleDto, CreateTenantDto, CreateClientDto) + - UpdateXxxDto.cs (UpdateUserDto, UpdateRoleDto, UpdateTenantDto, UpdateClientDto) + - XxxDto.cs (UserDto, RoleDto, TenantDto, OAuthClientDto, GatewayDto) + - XxxQueryDto.cs (UserQueryDto, RoleQueryDto, TenantQueryDto, OAuthClientQueryDto) + - `PaginationDto.cs` - 分页结果 + - `ResetPasswordDto.cs` - 密码重置 + - `TenantSettingsDto.cs` - 租户设置 + +## 关键文件位置 + +**入口点:** +- `src/Program.cs` - 应用启动配置和服务注册 + +**配置:** +- `src/appsettings.json` - 应用配置 +- `src/appsettings.Development.json` - 开发环境配置 + +**核心逻辑:** +- `src/Services/UserService.cs` - 用户服务实现 +- `src/Controllers/UsersController.cs` - 用户 API + +## 命名约定 + +**文件:** +- PascalCase:`UserService.cs`、`UsersController.cs` + +**目录:** +- PascalCase:`Controllers/`、`Services/`、`Models/Dtos/` + +**类/接口:** +- PascalCase:`UserService`、`IUserService` + +## 新增代码位置 + +**新增功能:** +- API 端点:`src/Controllers/` +- 业务逻辑:`src/Services/` +- DTO:`src/Models/Dtos/` + +**新增测试:** +- 建议位置:单独的测试项目(如 `tests/` 目录) + +--- + +*结构分析:2026-02-28* diff --git a/.planning/codebase/TESTING.md b/.planning/codebase/TESTING.md new file mode 100644 index 0000000..3cba314 --- /dev/null +++ b/.planning/codebase/TESTING.md @@ -0,0 +1,144 @@ +# 测试模式 + +**分析日期:** 2026-02-28 + +## 测试框架 + +**未检测到测试框架:** +- 当前项目未包含测试项目 +- 建议添加 xUnit、NUnit 或 MSTest + +**推荐配置:** +- 框架:xUnit +- Mock 库:Moq +- 集成测试:Microsoft.AspNetCore.Mvc.Testing + +## 测试文件组织 + +**建议结构:** +``` +tests/ +├── Fengling.Console.Tests/ +│ ├── Unit/ +│ │ ├── Services/ +│ │ └── Controllers/ +│ └── Integration/ +``` + +## 测试结构 + +**单元测试示例:** +```csharp +public class UserServiceTests +{ + private readonly Mock> _userManagerMock; + private readonly UserService _userService; + + public UserServiceTests() + { + _userManagerMock = new Mock>(...); + _userService = new UserService(...); + } + + [Fact] + public async Task GetUsersAsync_ReturnsPagedResults() + { + // Arrange + var expectedUsers = new List { ... }; + + // Act + var result = await _userService.GetUsersAsync(1, 10); + + // Assert + Assert.Equal(expectedUsers.Count, result.TotalCount); + } +} +``` + +## 模拟 (Mocking) + +**常用 Mock 库:** +- Moq - 主流 Mock 框架 + +**Mock 对象:** +```csharp +var mockUserManager = new Mock>( + store: mockStore.Object, + optionsAccessor: new Mock>().Object, + passwordHasher: new Mock>().Object, + validators: new List>(), + keyNormalizer: new Mock().Object, + errors: new IdentityErrorDescriber(), + logger: new Mock>>().Object, + services: new Mock().Object); +``` + +## Fixture 和工厂 + +**测试数据:** +- 使用静态工厂方法创建测试数据 +- 每个测试方法独立,不共享状态 + +**示例:** +```csharp +public static class TestData +{ + public static CreateUserDto CreateValidUserDto() => new CreateUserDto + { + UserName = "testuser", + Email = "test@example.com", + Password = "Test@123456", + RealName = "Test User" + }; +} +``` + +## 测试类型 + +**单元测试:** +- 范围:Service 层业务逻辑 +- 重点:边界条件、异常处理 + +**集成测试:** +- 范围:Controller API 端点 +- 使用:Microsoft.AspNetCore.Mvc.Testing + +## 常见模式 + +**异步测试:** +```csharp +[Fact] +public async Task CreateUserAsync_ValidInput_ReturnsCreatedUser() +{ + // Arrange + var dto = TestData.CreateValidUserDto(); + + // Act + var result = await _userService.CreateUserAsync(dto); + + // Assert + Assert.NotNull(result); + Assert.Equal(dto.UserName, result.UserName); +} +``` + +**异常测试:** +```csharp +[Fact] +public async Task CreateUserAsync_DuplicateUser_ThrowsException() +{ + // Arrange + var dto = TestData.CreateValidUserDto(); + _userManagerMock + .Setup(x => x.CreateAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(IdentityResult.Failed(new IdentityError { Description = "Duplicate" })); + + // Act & Assert + await Assert.ThrowsAsync(() => + _userService.CreateUserAsync(dto)); +} +``` + +--- + +*测试分析:2026-02-28*