init
This commit is contained in:
commit
619518e7bf
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
|
||||
.idea/
|
||||
/.vs
|
||||
/Fake.sln.DotSettings.user
|
||||
|
||||
Logs/
|
||||
|
||||
node_modules/
|
||||
7
NuGet.Config
Normal file
7
NuGet.Config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="xiaolipro.cn" value="https://baget.xiaolipro.cn/v3/index.json" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
180
README.md
Normal file
180
README.md
Normal file
@ -0,0 +1,180 @@
|
||||
# SimpleAdmin API
|
||||
|
||||
基于 Fake 框架的简单管理系统后端 API。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **.NET 8.0** - 最新的 .NET 平台
|
||||
- **Fake Framework** - 模块化应用框架
|
||||
- **Entity Framework Core** - ORM 框架
|
||||
- **SQL Server** - 数据库
|
||||
- **JWT** - 身份认证
|
||||
- **Swagger** - API 文档
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ 模块化架构
|
||||
- ✅ 自动 API 生成(ApplicationService 自动转换为 Controller)
|
||||
- ✅ RBAC 权限管理
|
||||
- ✅ JWT 认证
|
||||
- ✅ Swagger 文档
|
||||
- ✅ 依赖注入
|
||||
- ✅ 工作单元
|
||||
- ✅ 审计日志
|
||||
|
||||
## 开始使用
|
||||
|
||||
### 前置要求
|
||||
|
||||
- .NET 8.0 SDK
|
||||
- SQL Server (LocalDB 或完整版)
|
||||
|
||||
### 配置数据库
|
||||
|
||||
修改 `appsettings.json` 中的连接字符串:
|
||||
|
||||
```json
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"Default": "Server=(localdb)\\mssqllocaldb;Database=SimpleAdminDb;Trusted_Connection=true;MultipleActiveResultSets=true"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 数据库迁移
|
||||
|
||||
```bash
|
||||
# 添加迁移
|
||||
dotnet ef migrations add InitialCreate --project ../modules/rbac/Fake.Rbac.Infrastructure
|
||||
|
||||
# 更新数据库
|
||||
dotnet ef database update --project ../modules/rbac/Fake.Rbac.Infrastructure
|
||||
```
|
||||
|
||||
### 运行项目
|
||||
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
||||
|
||||
访问 http://localhost:5000 查看 Swagger 文档。
|
||||
|
||||
## 默认账号
|
||||
|
||||
系统会自动创建默认管理员账号:
|
||||
|
||||
- 账号:admin
|
||||
- 密码:123456
|
||||
- 角色:超级管理员
|
||||
|
||||
**⚠️ 重要:请在生产环境中立即修改默认密码!**
|
||||
|
||||
## API 端点
|
||||
|
||||
### 认证 API
|
||||
|
||||
- `POST /api/auth/login` - 用户登录
|
||||
- `GET /api/auth/current` - 获取当前用户信息
|
||||
- `PUT /api/auth/password` - 修改密码
|
||||
|
||||
### 用户管理 API
|
||||
|
||||
- `GET /api/rbac/user/list` - 获取用户列表
|
||||
- `GET /api/rbac/user/{id}` - 获取用户详情
|
||||
- `POST /api/rbac/user` - 创建用户
|
||||
- `PUT /api/rbac/user/{id}` - 更新用户
|
||||
- `DELETE /api/rbac/user/{id}` - 删除用户
|
||||
- `PUT /api/rbac/user/{id}/roles` - 分配角色
|
||||
- `GET /api/rbac/user/{id}/permissions` - 获取用户权限
|
||||
|
||||
### 角色管理 API
|
||||
|
||||
- `GET /api/rbac/role/list` - 获取角色列表
|
||||
- `GET /api/rbac/role/all` - 获取所有角色
|
||||
- `GET /api/rbac/role/{id}` - 获取角色详情
|
||||
- `POST /api/rbac/role` - 创建角色
|
||||
- `PUT /api/rbac/role/{id}` - 更新角色
|
||||
- `DELETE /api/rbac/role/{id}` - 删除角色
|
||||
- `PUT /api/rbac/role/{id}/permissions` - 分配权限
|
||||
|
||||
### 菜单管理 API
|
||||
|
||||
- `GET /api/rbac/menu/tree` - 获取菜单树
|
||||
- `GET /api/rbac/menu/user/{userId}` - 获取用户菜单
|
||||
- `GET /api/rbac/menu/{id}` - 获取菜单详情
|
||||
- `POST /api/rbac/menu` - 创建菜单
|
||||
- `PUT /api/rbac/menu/{id}` - 更新菜单
|
||||
- `DELETE /api/rbac/menu/{id}` - 删除菜单
|
||||
|
||||
### 权限管理 API
|
||||
|
||||
- `GET /api/rbac/permission/all` - 获取所有权限
|
||||
- `GET /api/rbac/permission/tree` - 获取权限树
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
SimpleAdmin.Api/
|
||||
├── Controllers/ # 控制器(手动创建的)
|
||||
├── Program.cs # 程序入口
|
||||
├── SimpleAdminApiModule.cs # 主模块配置
|
||||
├── appsettings.json # 配置文件
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Fake 框架特性
|
||||
|
||||
### 自动 API 生成
|
||||
|
||||
所有继承自 `ApplicationService` 的服务会自动生成对应的 API 端点,无需手动创建 Controller。
|
||||
|
||||
### 模块化
|
||||
|
||||
通过 `[DependsOn]` 特性声明模块依赖:
|
||||
|
||||
```csharp
|
||||
[DependsOn(
|
||||
typeof(FakeAspNetCoreModule),
|
||||
typeof(FakeRbacApplicationModule)
|
||||
)]
|
||||
public class SimpleAdminApiModule : FakeModule
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 依赖注入
|
||||
|
||||
框架自动注册服务,支持:
|
||||
- `ITransientDependency` - 瞬时
|
||||
- `IScopedDependency` - 作用域
|
||||
- `ISingletonDependency` - 单例
|
||||
|
||||
### 工作单元
|
||||
|
||||
应用服务方法自动包装在工作单元中,支持事务管理。
|
||||
|
||||
## JWT 配置
|
||||
|
||||
JWT 配置在 `appsettings.json` 中:
|
||||
|
||||
```json
|
||||
{
|
||||
"JwtSettings": {
|
||||
"SecretKey": "your-secret-key-here",
|
||||
"ExpiryInMinutes": 60
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## CORS 配置
|
||||
|
||||
默认允许的前端地址:
|
||||
- http://localhost:3000
|
||||
- http://localhost:5173
|
||||
|
||||
可在 `SimpleAdminApiModule.cs` 中修改。
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT
|
||||
44
SimpleAdmin.sln
Normal file
44
SimpleAdmin.sln
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleAdmin.Api", "src\SimpleAdmin.Api.csproj", "{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "items", "items", "{BE5132AD-C95E-4CB7-AFBD-0D4838AFD48C}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
NuGet.Config = NuGet.Config
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{F6418A25-D1B2-48E1-BDCA-80CC5262BB18} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
28
src/Program.cs
Normal file
28
src/Program.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using Serilog;
|
||||
using SimpleAdmin.Api;
|
||||
|
||||
var builder = WebApplication.CreateSlimBuilder(args);
|
||||
builder.Configuration.AddConsul("idwms/common", source => source.ReloadOnChange = true);
|
||||
builder.Configuration.AddConsul("idwms/admin", source => source.ReloadOnChange = true);
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(builder.Configuration)
|
||||
.CreateLogger();
|
||||
|
||||
try
|
||||
{
|
||||
builder.WebHost.UseUrls(builder.Configuration.GetSection("App:Urls").Get<string[]>() ?? []);
|
||||
builder.Host.UseAutofac().UseSerilog();
|
||||
builder.Services.AddApplication<SimpleAdminApiModule>();
|
||||
var app = builder.Build();
|
||||
app.InitializeApplication();
|
||||
await app.RunAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "G");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
34
src/Properties/launchSettings.json
Normal file
34
src/Properties/launchSettings.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:22279",
|
||||
"sslPort": 44353
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"dev": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "",
|
||||
"applicationUrl": "http://localhost:5281",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"staging": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"launchUrl": "",
|
||||
"applicationUrl": "http://localhost:5281",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Staging",
|
||||
"ASPNETCORE_PATHBASE": "/admin"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/SimpleAdmin.Api.csproj
Normal file
18
src/SimpleAdmin.Api.csproj
Normal file
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>e3d506cf-f5ce-4ba5-bc8e-ab2c179f3034</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Fake.Autofac" Version="8.0.5.8" />
|
||||
<PackageReference Include="Fake.Consul" Version="8.0.5.8" />
|
||||
<PackageReference Include="Fake.Rbac.Application" Version="8.0.5.8" />
|
||||
<PackageReference Include="Fake.Serilog" Version="8.0.5.8" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
6
src/SimpleAdmin.Api.http
Normal file
6
src/SimpleAdmin.Api.http
Normal file
@ -0,0 +1,6 @@
|
||||
@SimpleAdmin.Api_HostAddress = http://localhost:5281
|
||||
|
||||
GET {{SimpleAdmin.Api_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
89
src/SimpleAdminApiModule.cs
Normal file
89
src/SimpleAdminApiModule.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using Fake.AspNetCore;
|
||||
using Fake.Autofac;
|
||||
using Fake.Modularity;
|
||||
using Fake.Rbac.Application;
|
||||
using Fake.Rbac.Infrastructure;
|
||||
using Fake.AspNetCore.Auditing;
|
||||
using Fake.AspNetCore.Mvc;
|
||||
using Fake.Serilog;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
|
||||
namespace SimpleAdmin.Api;
|
||||
|
||||
[DependsOn(
|
||||
typeof(FakeAutofacModule),
|
||||
typeof(FakeRbacApplicationModule),
|
||||
typeof(FakeRbacInfrastructureModule),
|
||||
typeof(FakeSerilogModule)
|
||||
)]
|
||||
public class SimpleAdminApiModule : FakeModule
|
||||
{
|
||||
private const string DefaultCorsPolicyName = "default";
|
||||
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
var services = context.Services;
|
||||
var configuration = context.Services.GetConfiguration();
|
||||
|
||||
// 配置动态 API - 扫描 RBAC 应用服务
|
||||
services.Configure<FakeAspNetCoreMvcOptions>(options =>
|
||||
{
|
||||
options.ApplicationServices2Controller<FakeRbacApplicationModule>(settings =>
|
||||
{
|
||||
settings.RootPath = "rbac";
|
||||
});
|
||||
});
|
||||
|
||||
services.AddFakeAspNetCoreAuditing();
|
||||
|
||||
// 添加 Fake Swagger 支持
|
||||
services.AddFakeSwaggerGen(addSecurity: true);
|
||||
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(DefaultCorsPolicyName, builder =>
|
||||
{
|
||||
builder.WithOrigins(configuration.GetSection("App:CorsOrigins").Get<string[]>() ?? [])
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
//新增如下两行
|
||||
options.KnownNetworks.Clear();
|
||||
options.KnownProxies.Clear();
|
||||
});
|
||||
}
|
||||
|
||||
public override void ConfigureApplication(ApplicationConfigureContext context)
|
||||
{
|
||||
var app = context.GetWebApplication();
|
||||
|
||||
// 虚拟路由-网关适配
|
||||
app.UsePathBase(app.Configuration["ASPNETCORE_PATHBASE"]);
|
||||
|
||||
// Swagger
|
||||
app.UseFakeSwagger();
|
||||
// 异常处理
|
||||
app.UseFakeExceptionHandling();
|
||||
// CORS
|
||||
app.UseCors("Default");
|
||||
|
||||
// 静态文件服务(用于头像等上传文件)
|
||||
app.UseStaticFiles();
|
||||
|
||||
// 路由 - 必须在认证和授权之前
|
||||
app.UseRouting();
|
||||
|
||||
// 认证和授权
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
// 端点映射
|
||||
app.MapControllers();
|
||||
}
|
||||
}
|
||||
28
src/SimpleJwtService.cs
Normal file
28
src/SimpleJwtService.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Security.Claims;
|
||||
using Fake.AspNetCore.Authentication;
|
||||
using Fake.DependencyInjection;
|
||||
using Fake.Rbac.Application.Jwt;
|
||||
using Fake.Rbac.Application.Services;
|
||||
using Fake.Rbac.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace SimpleAdmin.Api;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义simple-admin auth jwt service
|
||||
/// </summary>
|
||||
[Dependency(Replace = true)]
|
||||
public class SimpleJwtService(IOptions<JwtOptions> jwtOptions, IUserService userService, FakeRbacDbContext rbacDbContext)
|
||||
: JwtService(jwtOptions, userService)
|
||||
{
|
||||
public override async Task<List<Claim>> GenerateClaimsByUserIdAsync(Guid userId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var claims = await base.GenerateClaimsByUserIdAsync(userId, cancellationToken);
|
||||
var mapId = await rbacDbContext.Database.SqlQuery<int>($"select userid as value from user where id = {userId}")
|
||||
.FirstAsync(cancellationToken);
|
||||
claims.Add(new Claim("mapId", mapId.ToString()));
|
||||
return claims;
|
||||
}
|
||||
}
|
||||
9
src/appsettings.Development.json
Normal file
9
src/appsettings.Development.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Microsoft.EntityFrameworkCore": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/appsettings.json
Normal file
8
src/appsettings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"UseLocalConfigs": false,
|
||||
"Consul": {
|
||||
"Address": "https://consul.nanafa.com",
|
||||
// 用户机密
|
||||
"Token": ""
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
Loading…
Reference in New Issue
Block a user