Merge branch 'dev_add_auth_1029' into 'master'
Dev add auth 1029 See merge request ql/apismnagaer_backend!8
This commit is contained in:
commit
5d407e7225
@ -13,7 +13,12 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Serilog" Version="4.1.0" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.MariaDB" Version="1.0.1" />
|
||||||
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
|
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@ -9,6 +9,8 @@ namespace Apimanager_backend.Config
|
|||||||
public MyAutomapper()
|
public MyAutomapper()
|
||||||
{
|
{
|
||||||
CreateMap<User,UserInfoDto>();
|
CreateMap<User,UserInfoDto>();
|
||||||
|
CreateMap<CreateUserDto, User>()
|
||||||
|
.ForMember(dest => dest.PassHash, opt => opt.MapFrom(src => src.Password));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
using Apimanager_backend.Services;
|
using Apimanager_backend.Dtos;
|
||||||
|
using Apimanager_backend.Services;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@ -18,6 +20,7 @@ namespace Apimanager_backend.Config
|
|||||||
services.AddScoped<IAuthService, AuthService>();
|
services.AddScoped<IAuthService, AuthService>();
|
||||||
services.AddSingleton<ITokenService, TokenService>();
|
services.AddSingleton<ITokenService, TokenService>();
|
||||||
services.AddSingleton<IRefreshTokenService, RefreshTokenService>();
|
services.AddSingleton<IRefreshTokenService, RefreshTokenService>();
|
||||||
|
services.AddSingleton<IEmailService, EmailService>();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
public static IServiceCollection AddJWTService(this IServiceCollection services,IConfiguration configuration)
|
public static IServiceCollection AddJWTService(this IServiceCollection services,IConfiguration configuration)
|
||||||
@ -28,6 +31,7 @@ namespace Apimanager_backend.Config
|
|||||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
.AddJwtBearer(options =>
|
.AddJwtBearer(options =>
|
||||||
{
|
{
|
||||||
|
//jwt参数
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
{
|
{
|
||||||
ValidateIssuer = true,
|
ValidateIssuer = true,
|
||||||
@ -38,11 +42,45 @@ namespace Apimanager_backend.Config
|
|||||||
ValidAudience = jwtSettings["Audience"],
|
ValidAudience = jwtSettings["Audience"],
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(key)
|
IssuerSigningKey = new SymmetricSecurityKey(key)
|
||||||
};
|
};
|
||||||
|
//添加自定义响应处理函数
|
||||||
|
options.Events = new JwtBearerEvents
|
||||||
|
{
|
||||||
|
OnChallenge = new Func<JwtBearerChallengeContext, Task>(JwtTokenErrorEventFunc),
|
||||||
|
OnForbidden = new Func<ForbiddenContext, Task>(JwtPermissionEventFunc)
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
//redis配置
|
//redis配置
|
||||||
services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(configuration["Redis:ConnectionString"]));
|
services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(configuration["Redis:ConnectionString"]));
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// token无效事件处理函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async static Task JwtTokenErrorEventFunc(JwtBearerChallengeContext context)
|
||||||
|
{
|
||||||
|
context.Response.ContentType = "application/json";
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code: 1002,
|
||||||
|
message: "用户未登录或认证失败",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||||
|
await context.Response.WriteAsync(JsonConvert.SerializeObject(res));
|
||||||
|
context.HandleResponse();
|
||||||
|
}
|
||||||
|
public async static Task JwtPermissionEventFunc(ForbiddenContext context)
|
||||||
|
{
|
||||||
|
context.Response.ContentType = "application/json";
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code: 2006,
|
||||||
|
message: "用户无权限进行该操作",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||||
|
await context.Response.WriteAsync(JsonConvert.SerializeObject(res));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
133
Apimanager_backend/Controllers/AdminController.cs
Normal file
133
Apimanager_backend/Controllers/AdminController.cs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
using Apimanager_backend.Dtos;
|
||||||
|
using Apimanager_backend.Exceptions;
|
||||||
|
using Apimanager_backend.Services;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]/[action]")]
|
||||||
|
[ApiController]
|
||||||
|
public class AdminController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IAdminService adminService;
|
||||||
|
private readonly IUserService userService;
|
||||||
|
public AdminController(IAdminService service,IUserService userService)
|
||||||
|
{
|
||||||
|
this.adminService = service;
|
||||||
|
this.userService = userService;
|
||||||
|
}
|
||||||
|
#region 获取用户列表
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public async Task<ActionResult<ResponseBase<List<UserInfoDto>>>> UserList(int pageIndex,int pageSize,bool desc)
|
||||||
|
{
|
||||||
|
var users = await adminService.GetUsersAsync(pageIndex,pageSize,desc);
|
||||||
|
var res = new ResponseBase<List<UserInfoDto>>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data:users
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 获取用户信息
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public async Task<ActionResult<ResponseBase<UserInfoDto?>>> UserInfo(int userId)
|
||||||
|
{
|
||||||
|
var userInfo = await userService.GetUserAsync(userId);
|
||||||
|
var res = new ResponseBase<UserInfoDto?>(
|
||||||
|
code: 1000,
|
||||||
|
message: "Success",
|
||||||
|
data: userInfo
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 删除用户
|
||||||
|
[HttpDelete]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public async Task<ActionResult<ResponseBase<object?>>> DeleteUser(int userId)
|
||||||
|
{
|
||||||
|
await adminService.DeleteUserAsync(userId);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 添加用户
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public async Task<ActionResult<ResponseBase<UserInfoDto?>>> AddUser([FromBody]CreateUserDto dto)
|
||||||
|
{
|
||||||
|
var userInfo = await adminService.CreateUserAsync(dto);
|
||||||
|
var res = new ResponseBase<UserInfoDto?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data: userInfo
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 禁用用户
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public async Task<ActionResult<ResponseBase<object?>>> Ban(int userId)
|
||||||
|
{
|
||||||
|
await adminService.BanUserAsync(userId);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 取消禁用用户
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public async Task<ActionResult<ResponseBase<object?>>> UnBan(int userId)
|
||||||
|
{
|
||||||
|
await adminService.UnbanUserAsync(userId);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data:null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 更新用户信息
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
|
public async Task<ActionResult<ResponseBase<UserInfoDto?>>> UpdateUser([FromQuery]int userId,[FromBody]AdminUpdateUserDto dto)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userInfo = await adminService.UpdateUserAsync(userId, dto);
|
||||||
|
var res = new ResponseBase<UserInfoDto?>(
|
||||||
|
code: 1000,
|
||||||
|
message: "Success",
|
||||||
|
data: userInfo
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch(BaseException e)
|
||||||
|
{
|
||||||
|
var res = new ResponseBase<UserInfoDto?>(
|
||||||
|
code: e.code,
|
||||||
|
message:e.message,
|
||||||
|
data:null
|
||||||
|
);
|
||||||
|
return NotFound(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ using Apimanager_backend.Services;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.VisualBasic;
|
||||||
|
|
||||||
namespace Apimanager_backend.Controllers
|
namespace Apimanager_backend.Controllers
|
||||||
{
|
{
|
||||||
@ -31,52 +32,35 @@ namespace Apimanager_backend.Controllers
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<ResponseBase<UserInfoDto>>> Login([FromBody] UserLoginDto dto)
|
public async Task<ActionResult<ResponseBase<UserInfoDto>>> Login([FromBody] UserLoginDto dto)
|
||||||
{
|
{
|
||||||
try
|
UserInfoDto user = await authService.LoginAsync(dto.UserName, dto.Password);
|
||||||
{
|
//生成token
|
||||||
UserInfoDto user = await authService.LoginAsync(dto.UserName, dto.Password);
|
string token = tokenService.GenerateAccessToken(user.Id.ToString(), user.Roles);
|
||||||
//生成token
|
//生成refreshtoken
|
||||||
string token = tokenService.GenerateAccessToken(user.Id.ToString(),user.Roles);
|
string refreshToken = await refreshTokenService.CreateRefereshTokenAsync(user.Id.ToString());
|
||||||
//生成refreshtoken
|
var responseInfo = new ResponseBase<LoginResponseDto>(
|
||||||
string refreshToken = await refreshTokenService.CreateRefereshTokenAsync(user.Id.ToString());
|
code: 2000,
|
||||||
var responseInfo = new ResponseBase<LoginResponseDto>(
|
message: "Login successful",
|
||||||
code: 2000,
|
data: new LoginResponseDto
|
||||||
message: "Login successful",
|
{
|
||||||
data: new LoginResponseDto
|
UserInfo = user,
|
||||||
{
|
Token = token,
|
||||||
UserInfo = user,
|
RefreshToken = refreshToken
|
||||||
Token = token,
|
}
|
||||||
RefreshToken = refreshToken
|
);
|
||||||
}
|
return Ok(responseInfo);
|
||||||
);
|
|
||||||
return Ok(responseInfo);
|
|
||||||
}
|
|
||||||
catch (BaseException e)
|
|
||||||
{
|
|
||||||
|
|
||||||
//错误时,构建错误信息对象
|
|
||||||
var responseInfo = new ResponseBase<object?>(
|
|
||||||
code: e.code,
|
|
||||||
message: e.message,
|
|
||||||
data: null
|
|
||||||
);
|
|
||||||
|
|
||||||
return e.code switch
|
|
||||||
{
|
|
||||||
2001 => Unauthorized(responseInfo),
|
|
||||||
2002 => Unauthorized(responseInfo),
|
|
||||||
_ => StatusCode(503)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 令牌刷新
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto">传入用户令牌</param>
|
||||||
|
/// <returns>返回新令牌</returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<ResponseBase<RefreshResponseDto?>>> Refresh([FromBody]RefreshResponseDto dto)
|
public async Task<ActionResult<ResponseBase<RefreshResponseDto?>>> Refresh([FromBody]RefreshResponseDto dto)
|
||||||
{
|
{
|
||||||
try
|
var IsRefreshToken = await refreshTokenService.ValidateRefreshTokenAsync(dto.UserId.ToString(),dto.RefreshToken);
|
||||||
{
|
|
||||||
var userId = await refreshTokenService.ValidateRefreshTokenAsync(dto.RefreshToken);
|
|
||||||
//刷新令牌无效
|
//刷新令牌无效
|
||||||
if (userId == null)
|
if (!IsRefreshToken)
|
||||||
{
|
{
|
||||||
var ret = new ResponseBase<RefreshResponseDto?>(
|
var ret = new ResponseBase<RefreshResponseDto?>(
|
||||||
code: 2008,
|
code: 2008,
|
||||||
@ -86,27 +70,103 @@ namespace Apimanager_backend.Controllers
|
|||||||
return Unauthorized(ret);
|
return Unauthorized(ret);
|
||||||
}
|
}
|
||||||
//获取刷新令牌对应用户信息
|
//获取刷新令牌对应用户信息
|
||||||
var userInfo = await userService.GetUserAsync(int.Parse(userId));
|
var userInfo = await userService.GetUserAsync(dto.UserId);
|
||||||
//重新生成令牌
|
//重新生成令牌
|
||||||
var token = tokenService.GenerateAccessToken(userInfo.Id.ToString(), userInfo.Roles);
|
var token = tokenService.GenerateAccessToken(userInfo.Id.ToString(), userInfo.Roles);
|
||||||
//刷新刷新令牌有效期(小于三天才会刷新)
|
//刷新刷新令牌有效期(小于三天才会刷新)
|
||||||
await refreshTokenService.UpdateRefreshTokenAsync(dto.RefreshToken);
|
await refreshTokenService.UpdateRefreshTokenAsync(userInfo.Id.ToString());
|
||||||
var result = new ResponseBase<RefreshResponseDto?>(
|
var result = new ResponseBase<RefreshResponseDto?>(
|
||||||
code: 1000,
|
code: 1000,
|
||||||
message: "Success",
|
message: "Success",
|
||||||
data: new RefreshResponseDto
|
data: new RefreshResponseDto
|
||||||
{
|
{
|
||||||
|
UserId = dto.UserId,
|
||||||
Token = token,
|
Token = token,
|
||||||
RefreshToken = dto.RefreshToken
|
RefreshToken = dto.RefreshToken
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}catch(BaseException e)
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 用户注册
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ResponseBase<UserInfoDto?>>> Register(RegisterRequestDto requestDto)
|
||||||
|
{
|
||||||
|
var isUsernameExist = await userService.IsUsernameExist(requestDto.Username);
|
||||||
|
if (isUsernameExist)
|
||||||
{
|
{
|
||||||
|
var errorRes = new ResponseBase<UserInfoDto?>(
|
||||||
|
code: 2003,
|
||||||
|
message: "用户名已存在",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return StatusCode(409, errorRes);
|
||||||
}
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userInfo = await authService.RegisterAsync(requestDto);
|
||||||
|
var res = new ResponseBase<UserInfoDto?>(
|
||||||
|
code: 1000,
|
||||||
|
message: "Success",
|
||||||
|
data: userInfo
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
catch (BaseException e)
|
||||||
|
{
|
||||||
|
var res = new ResponseBase<UserInfoDto?>(
|
||||||
|
code: e.code,
|
||||||
|
message: e.message,
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return StatusCode(500, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 发送邮箱校验码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="registerRequestDto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ResponseBase<object?>>> SendValidateCode([FromQuery]string email)
|
||||||
|
{
|
||||||
|
//检测邮箱是否被使用
|
||||||
|
var emailIsUse = await userService.IsEmailExist(email);
|
||||||
|
if (emailIsUse)
|
||||||
|
{
|
||||||
|
var errorRes = new ResponseBase<object?>(
|
||||||
|
code:2005,
|
||||||
|
message: "邮箱已存在",
|
||||||
|
data:null
|
||||||
|
);
|
||||||
|
return StatusCode(409,errorRes);
|
||||||
|
}
|
||||||
|
//发送注册验证码
|
||||||
|
await authService.SendRegisterCodeAsync(email);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
[Authorize(Roles = "User")]
|
||||||
|
public async Task<ActionResult<ResponseBase<object?>>> Logout()
|
||||||
|
{
|
||||||
|
var userId = User.Claims.First(x => x.ValueType == "userId").Value;
|
||||||
|
await refreshTokenService.DeleterRefreshTokenAsync(userId);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,9 @@ using Apimanager_backend.Services;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Apimanager_backend.Filters;
|
using Apimanager_backend.Filters;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Apimanager_backend.Models;
|
||||||
|
using System.Security.Claims;
|
||||||
|
|
||||||
namespace Apimanager_backend.Controllers
|
namespace Apimanager_backend.Controllers
|
||||||
{
|
{
|
||||||
@ -16,6 +19,73 @@ namespace Apimanager_backend.Controllers
|
|||||||
{
|
{
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 获取用户个人信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize(Roles = "User")]
|
||||||
|
public async Task<ActionResult<ResponseBase<UserInfoDto>>> UserInfo()
|
||||||
|
{
|
||||||
|
var userId = User.Claims.First(x => x.Type == "userId").Value;
|
||||||
|
var userInfo = await userService.GetUserAsync(int.Parse(userId));
|
||||||
|
var res = new ResponseBase<UserInfoDto>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data:userInfo
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 重置用户密码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ResponseBase<object?>>> Resetpassword([FromBody]ResetPasswordDto dto)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await userService.ResetPasswordAsync(dto.Email, dto.Code, dto.NewPassword);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}catch(BaseException e)
|
||||||
|
{
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:e.code,
|
||||||
|
message:e.message,
|
||||||
|
data:null
|
||||||
|
);
|
||||||
|
return StatusCode(400,res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ResponseBase<object?>>> SendResetEmail([FromQuery]string email)
|
||||||
|
{
|
||||||
|
await userService.SendResetPasswordEmailAsync(email);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code: 1000,
|
||||||
|
message: "Success",
|
||||||
|
data: null
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize(Roles = "User")]
|
||||||
|
public async Task<ActionResult<ResponseBase<UserInfoDto?>>> Update([FromBody]UpdateUserDto dto)
|
||||||
|
{
|
||||||
|
var userId = User.Claims.First(x => x.ValueType == "userId").Value;
|
||||||
|
var userInfo = await userService.UpdateUserAsync(int.Parse(userId),dto);
|
||||||
|
var res = new ResponseBase<object?>(
|
||||||
|
code:1000,
|
||||||
|
message:"Success",
|
||||||
|
data:userInfo
|
||||||
|
);
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,8 @@ namespace Apimanager_backend.Data
|
|||||||
public DbSet<UserPackage> UserPackages { get; set; }
|
public DbSet<UserPackage> UserPackages { get; set; }
|
||||||
//用户角色表
|
//用户角色表
|
||||||
public DbSet<UserRole> UserRoles { get; set; }
|
public DbSet<UserRole> UserRoles { get; set; }
|
||||||
|
//日志表
|
||||||
|
public DbSet<Log> Logs { get; set; }
|
||||||
public ApiContext(DbContextOptions<ApiContext> options) : base(options) { }
|
public ApiContext(DbContextOptions<ApiContext> options) : base(options) { }
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
@ -29,6 +31,11 @@ namespace Apimanager_backend.Data
|
|||||||
// 配置全局查询筛选器
|
// 配置全局查询筛选器
|
||||||
modelBuilder.Entity<User>().HasQueryFilter(u => !u.IsDelete);
|
modelBuilder.Entity<User>().HasQueryFilter(u => !u.IsDelete);
|
||||||
modelBuilder.Entity<Api>().HasQueryFilter(a => !a.IsDelete);
|
modelBuilder.Entity<Api>().HasQueryFilter(a => !a.IsDelete);
|
||||||
|
//配置日志表
|
||||||
|
modelBuilder.Entity<Log>().HasKey(x => x.Id);
|
||||||
|
modelBuilder.Entity<Log>()
|
||||||
|
.Property(x => x.Id)
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
8
Apimanager_backend/Dtos/AdminUpdateUserDto.cs
Normal file
8
Apimanager_backend/Dtos/AdminUpdateUserDto.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Apimanager_backend.Dtos
|
||||||
|
{
|
||||||
|
public class AdminUpdateUserDto
|
||||||
|
{
|
||||||
|
public string Password { get; set; }
|
||||||
|
public decimal Balance { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,16 @@
|
|||||||
namespace Apimanager_backend.Dtos
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Dtos
|
||||||
{
|
{
|
||||||
public class CreateUserDto
|
public class CreateUserDto
|
||||||
{
|
{
|
||||||
|
[Required(ErrorMessage = "用户名必填")]
|
||||||
|
[MaxLength(20,ErrorMessage = "用户名最大长度20字符")]
|
||||||
|
public string Username { get; set; }
|
||||||
|
[Required(ErrorMessage = "密码必填")]
|
||||||
|
public string Password { get; set; }
|
||||||
|
[EmailAddress(ErrorMessage = "邮箱格式错误")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,8 +4,10 @@ namespace Apimanager_backend.Dtos
|
|||||||
{
|
{
|
||||||
public class RefreshResponseDto
|
public class RefreshResponseDto
|
||||||
{
|
{
|
||||||
|
[Required(ErrorMessage = "用户ID必填!")]
|
||||||
|
public int UserId { get; set; }
|
||||||
public string? Token { get; set; }
|
public string? Token { get; set; }
|
||||||
[Required(ErrorMessage = "RefreshToken is required")]
|
[Required(ErrorMessage = "刷新令牌必填!")]
|
||||||
public string RefreshToken { get; set; }
|
public string RefreshToken { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
Apimanager_backend/Dtos/RegisterRequestDto.cs
Normal file
17
Apimanager_backend/Dtos/RegisterRequestDto.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Dtos
|
||||||
|
{
|
||||||
|
public class RegisterRequestDto
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "用户名必填!")]
|
||||||
|
[MaxLength(20,ErrorMessage = "用户名最长20字符!")]
|
||||||
|
public string Username { get; set; }
|
||||||
|
[Required(ErrorMessage = "密码必填!")]
|
||||||
|
public string Password { get; set; }
|
||||||
|
[Required(ErrorMessage = "邮箱必填!")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
[Required(ErrorMessage = "验证码必填!")]
|
||||||
|
public string VerificationCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Apimanager_backend/Dtos/ResetPasswordDto.cs
Normal file
9
Apimanager_backend/Dtos/ResetPasswordDto.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Apimanager_backend.Dtos
|
||||||
|
{
|
||||||
|
public class ResetPasswordDto
|
||||||
|
{
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string NewPassword { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,10 @@
|
|||||||
namespace Apimanager_backend.Dtos
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Dtos
|
||||||
{
|
{
|
||||||
public class UpdateUserDto
|
public class UpdateUserDto
|
||||||
{
|
{
|
||||||
|
public string? password { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
using Apimanager_backend.Dtos;
|
using Apimanager_backend.Dtos;
|
||||||
using Apimanager_backend.Exceptions;
|
using Apimanager_backend.Exceptions;
|
||||||
|
using Apimanager_backend.Tools;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
namespace Apimanager_backend.Filters.ExceptionFilter
|
namespace Apimanager_backend.Filters.ExceptionFilter
|
||||||
@ -17,25 +19,11 @@ namespace Apimanager_backend.Filters.ExceptionFilter
|
|||||||
message: exception.message,
|
message: exception.message,
|
||||||
data:null
|
data:null
|
||||||
);
|
);
|
||||||
//根据自定义错误码返回对应http状态码
|
int httpCode = StatusCodeHelper.GetHttpStatusCode(exception.code);
|
||||||
int code = 0;
|
context.Result = new JsonResult(res) {
|
||||||
switch (exception.code)
|
StatusCode = httpCode
|
||||||
{
|
};
|
||||||
case 1001:
|
context.ExceptionHandled = true;
|
||||||
case 1005:
|
|
||||||
case 2007:
|
|
||||||
case 4001:
|
|
||||||
code = 400;
|
|
||||||
break;
|
|
||||||
case 1002:
|
|
||||||
case 2001:
|
|
||||||
code = 401;
|
|
||||||
break;
|
|
||||||
case 1003:
|
|
||||||
case 2006:
|
|
||||||
case 3001:
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
442
Apimanager_backend/Migrations/20241103110714_update-logtable.Designer.cs
generated
Normal file
442
Apimanager_backend/Migrations/20241103110714_update-logtable.Designer.cs
generated
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Apimanager_backend.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ApiContext))]
|
||||||
|
[Migration("20241103110714_update-logtable")]
|
||||||
|
partial class updatelogtable
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.0")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Endpoint")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelete")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsThirdParty")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Method")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("varchar(200)");
|
||||||
|
|
||||||
|
b.Property<int?>("PackageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.ToTable("Apis");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ApiId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CallResult")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CallTime")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ApiId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("CallLogs");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CallLimit")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpiryDate")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("varchar(20)");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price")
|
||||||
|
.HasColumnType("decimal(65,30)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Apipackages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Exception")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LogLevel")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("MessageTemplate")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Properties")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Timestamp")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Logs");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("IpAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(45)
|
||||||
|
.HasColumnType("varchar(45)");
|
||||||
|
|
||||||
|
b.Property<string>("Operation")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("varchar(20)");
|
||||||
|
|
||||||
|
b.Property<int>("TargetId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("TargetType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("varchar(50)");
|
||||||
|
|
||||||
|
b.Property<string>("UserAgent")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("OperationLogs");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("Amount")
|
||||||
|
.HasColumnType("decimal(65,30)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("OrderNumber")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<int>("OrderType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ThirdPartyOrderId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OrderNumber")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("ThirdPartyOrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Orders");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("Balance")
|
||||||
|
.HasColumnType("decimal(65,30)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBan")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelete")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("PassHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(255)
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Email")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("Username")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PackageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("PurchasedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<int>("RemainingCalls")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("UserPackages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Role")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("UserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
|
||||||
|
.WithMany("Apis")
|
||||||
|
.HasForeignKey("PackageId");
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Apimanager_backend.Models.Api", "Api")
|
||||||
|
.WithMany("ApiCalls")
|
||||||
|
.HasForeignKey("ApiId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Apimanager_backend.Models.User", "User")
|
||||||
|
.WithMany("CallLogs")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Api");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Apimanager_backend.Models.User", "User")
|
||||||
|
.WithMany("operationLogs")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Apimanager_backend.Models.User", "User")
|
||||||
|
.WithMany("Orders")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
|
||||||
|
.WithMany("Packages")
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Apimanager_backend.Models.User", "User")
|
||||||
|
.WithMany("Packages")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Apimanager_backend.Models.User", "User")
|
||||||
|
.WithMany("Roles")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ApiCalls");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Apis");
|
||||||
|
|
||||||
|
b.Navigation("Packages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("CallLogs");
|
||||||
|
|
||||||
|
b.Navigation("Orders");
|
||||||
|
|
||||||
|
b.Navigation("Packages");
|
||||||
|
|
||||||
|
b.Navigation("Roles");
|
||||||
|
|
||||||
|
b.Navigation("operationLogs");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class updatelogtable : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -114,6 +114,40 @@ namespace Apimanager_backend.Migrations
|
|||||||
b.ToTable("Apipackages");
|
b.ToTable("Apipackages");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Exception")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LogLevel")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("MessageTemplate")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Properties")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Timestamp")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Logs");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
|
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
|||||||
18
Apimanager_backend/Models/Log.cs
Normal file
18
Apimanager_backend/Models/Log.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Models
|
||||||
|
{
|
||||||
|
[Table("Logs")]
|
||||||
|
public class Log
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public DateTime Timestamp { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
public string Exception { get; set; }
|
||||||
|
public string MessageTemplate { get; set; }
|
||||||
|
public string Properties { get; set; }
|
||||||
|
public string LogLevel { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,16 +35,16 @@ namespace Apimanager_backend.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否禁用
|
/// 是否禁用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsBan { get; set; } // boolean
|
public bool IsBan { get; set; } = false; // boolean
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否删除
|
/// 是否删除
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDelete { get; set; } // boolean
|
public bool IsDelete { get; set; } = false; // boolean
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 余额
|
/// 余额
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal Balance { get; set; } // Decimal(10)
|
public decimal Balance { get; set; } = 0; // Decimal(10)
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建时间,默认当前时间
|
/// 创建时间,默认当前时间
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
using Apimanager_backend.Config;
|
using Apimanager_backend.Config;
|
||||||
using Apimanager_backend.Data;
|
using Apimanager_backend.Data;
|
||||||
using Apimanager_backend.Filters;
|
using Apimanager_backend.Filters;
|
||||||
|
using Apimanager_backend.Filters.ExceptionFilter;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Serilog;
|
||||||
|
using Serilog.Sinks.MariaDB.Extensions;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@ -12,15 +15,29 @@ IConfiguration configuration = new ConfigurationBuilder()
|
|||||||
.SetBasePath(Directory.GetCurrentDirectory())
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||||
.Build();
|
.Build();
|
||||||
|
string? redStr = configuration["Redis:ConnectionString"];
|
||||||
string? constr = configuration.GetConnectionString("DefaultConnection");
|
string? constr = configuration.GetConnectionString("DefaultConnection");
|
||||||
|
//日志服务
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.MinimumLevel.Debug()
|
||||||
|
.WriteTo.Console()
|
||||||
|
.WriteTo.MariaDB(
|
||||||
|
connectionString: constr,
|
||||||
|
tableName: "Logs",
|
||||||
|
autoCreateTable:true
|
||||||
|
).CreateLogger();
|
||||||
|
builder.Host.UseSerilog();
|
||||||
|
|
||||||
builder.Services.AddDbContext<ApiContext>(option =>
|
builder.Services.AddDbContext<ApiContext>(option =>
|
||||||
option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr))
|
option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr))
|
||||||
);
|
);
|
||||||
builder.Services.AddAllService(configuration);
|
builder.Services.AddAllService(configuration);
|
||||||
builder.Services.AddControllers(options =>
|
builder.Services.AddControllers(options =>
|
||||||
{
|
{
|
||||||
|
//模型验证
|
||||||
options.Filters.Add<ModelValidationFilter>();
|
options.Filters.Add<ModelValidationFilter>();
|
||||||
|
//Exception过滤器
|
||||||
|
options.Filters.Add<generalExceptionFilter>();
|
||||||
}).ConfigureApiBehaviorOptions(option =>
|
}).ConfigureApiBehaviorOptions(option =>
|
||||||
{
|
{
|
||||||
option.SuppressModelStateInvalidFilter = true;
|
option.SuppressModelStateInvalidFilter = true;
|
||||||
@ -33,7 +50,6 @@ builder.Services.AddControllers(options =>
|
|||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
|||||||
112
Apimanager_backend/Services/AdminService.cs
Normal file
112
Apimanager_backend/Services/AdminService.cs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
using Apimanager_backend.Data;
|
||||||
|
using Apimanager_backend.Dtos;
|
||||||
|
using Apimanager_backend.Exceptions;
|
||||||
|
using Apimanager_backend.Models;
|
||||||
|
using AutoMapper;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Services
|
||||||
|
{
|
||||||
|
public class AdminService : IAdminService
|
||||||
|
{
|
||||||
|
private readonly ApiContext context;
|
||||||
|
private readonly IMapper mapper;
|
||||||
|
private readonly ILogger<IAdminService> logger;
|
||||||
|
public AdminService(ApiContext context, IMapper mapper, ILogger<IAdminService> logger)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.mapper = mapper;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
#region 禁用用户
|
||||||
|
public async Task BanUserAsync(int userId)
|
||||||
|
{
|
||||||
|
var user = await context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new BaseException(2004,"用户不存在");
|
||||||
|
}
|
||||||
|
user.IsBan = true;
|
||||||
|
context.Users.Update(user);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 新建用户
|
||||||
|
public async Task<UserInfoDto> CreateUserAsync(CreateUserDto dto)
|
||||||
|
{
|
||||||
|
//添加用户
|
||||||
|
var user = mapper.Map<User>(dto);
|
||||||
|
context.Users.Add(user);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
//添加默认角色
|
||||||
|
UserRole userRole = new UserRole
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
Role = "User"
|
||||||
|
};
|
||||||
|
|
||||||
|
context.UserRoles.Add(userRole);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
return mapper.Map<UserInfoDto>(user);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 删除用户
|
||||||
|
public async Task DeleteUserAsync(int userId)
|
||||||
|
{
|
||||||
|
var user = await context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new BaseException(2004, "用户不存在");
|
||||||
|
}
|
||||||
|
user.IsDelete = true;
|
||||||
|
context.Users.Update(user);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 获取用户列表
|
||||||
|
public async Task<List<UserInfoDto>> GetUsersAsync(int page, int pageSize, bool desc)
|
||||||
|
{
|
||||||
|
var query = context.Users.Where(x => true)
|
||||||
|
.OrderBy(x => x.Id);
|
||||||
|
//倒序
|
||||||
|
if (desc)
|
||||||
|
{
|
||||||
|
query = query.OrderByDescending(x => x.Id);
|
||||||
|
}
|
||||||
|
//分页
|
||||||
|
var users = await query.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize).ToListAsync();
|
||||||
|
return mapper.Map<List<UserInfoDto>>(users);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 禁用用户
|
||||||
|
public async Task UnbanUserAsync(int userId)
|
||||||
|
{
|
||||||
|
var user = await context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new BaseException(2004, "用户不存在");
|
||||||
|
}
|
||||||
|
user.IsBan = false;
|
||||||
|
context.Users.Update(user);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 更新用户信息
|
||||||
|
public async Task<UserInfoDto> UpdateUserAsync(int userId,AdminUpdateUserDto dto)
|
||||||
|
{
|
||||||
|
var user = await context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||||
|
if(user == null)
|
||||||
|
{
|
||||||
|
throw new BaseException(2004,"用户不存在");
|
||||||
|
}
|
||||||
|
user.PassHash = dto.Password;
|
||||||
|
user.Balance = dto.Balance;
|
||||||
|
context.Users.Update(user);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
return mapper.Map<UserInfoDto>(user);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,20 +2,30 @@
|
|||||||
using Apimanager_backend.Dtos;
|
using Apimanager_backend.Dtos;
|
||||||
using Apimanager_backend.Exceptions;
|
using Apimanager_backend.Exceptions;
|
||||||
using Apimanager_backend.Models;
|
using Apimanager_backend.Models;
|
||||||
|
using Apimanager_backend.Tools;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
namespace Apimanager_backend.Services
|
namespace Apimanager_backend.Services
|
||||||
{
|
{
|
||||||
public class AuthService:IAuthService
|
public class AuthService:IAuthService
|
||||||
{
|
{
|
||||||
private readonly ApiContext apiContext;
|
private readonly ApiContext apiContext;
|
||||||
|
private readonly ILogger<IAuthService> logger;
|
||||||
|
private readonly IConnectionMultiplexer redis;
|
||||||
|
private readonly IEmailService emailService;
|
||||||
private readonly IMapper mapper;
|
private readonly IMapper mapper;
|
||||||
public AuthService(ApiContext apiContext, IMapper automapper)
|
private readonly int DbIndex = 1;
|
||||||
|
public AuthService(ApiContext apiContext, IMapper automapper,ILogger<AuthService> logger,IConnectionMultiplexer redis,IEmailService emailService)
|
||||||
{
|
{
|
||||||
this.apiContext = apiContext;
|
this.apiContext = apiContext;
|
||||||
this.mapper = automapper;
|
this.mapper = automapper;
|
||||||
|
this.logger = logger;
|
||||||
|
this.redis = redis;
|
||||||
|
this.emailService = emailService;
|
||||||
}
|
}
|
||||||
|
#region 用户登录
|
||||||
public async Task<UserInfoDto> LoginAsync(string username, string password)
|
public async Task<UserInfoDto> LoginAsync(string username, string password)
|
||||||
{
|
{
|
||||||
//查找用户
|
//查找用户
|
||||||
@ -37,5 +47,63 @@ namespace Apimanager_backend.Services
|
|||||||
|
|
||||||
return mapper.Map<UserInfoDto>(user);
|
return mapper.Map<UserInfoDto>(user);
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
#region 用户注册
|
||||||
|
public async Task<UserInfoDto> RegisterAsync(RegisterRequestDto dto)
|
||||||
|
{
|
||||||
|
var db = redis.GetDatabase(DbIndex);
|
||||||
|
//获取邮箱对应验证码
|
||||||
|
var code = await db.StringGetAsync(dto.Email);
|
||||||
|
if(!code.HasValue || code.ToString() != dto.VerificationCode)
|
||||||
|
{
|
||||||
|
throw new BaseException(5005,"验证码错误");
|
||||||
|
}
|
||||||
|
User user = new User
|
||||||
|
{
|
||||||
|
Username = dto.Username,
|
||||||
|
PassHash = dto.Password,
|
||||||
|
Email = dto.Email,
|
||||||
|
IsBan = false,
|
||||||
|
IsDelete = false,
|
||||||
|
Balance = 0,
|
||||||
|
};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//添加新用户
|
||||||
|
await apiContext.Users.AddAsync(user);
|
||||||
|
await apiContext.SaveChangesAsync();
|
||||||
|
UserRole userRole = new UserRole
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
Role = "User"
|
||||||
|
};
|
||||||
|
await apiContext.UserRoles.AddAsync(userRole);
|
||||||
|
await apiContext.SaveChangesAsync();
|
||||||
|
return mapper.Map<UserInfoDto>(user);
|
||||||
|
}catch(Exception e)
|
||||||
|
{
|
||||||
|
throw new BaseException(1005,e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 发送注册验证码
|
||||||
|
public async Task SendRegisterCodeAsync(string email)
|
||||||
|
{
|
||||||
|
//生成随机码
|
||||||
|
string code = RandomCodeHelper.GetRandomCodeStr();
|
||||||
|
string subject = "注册验证码";
|
||||||
|
string body = $"您的注册验证码为:{code}<br>有效期60分钟!";
|
||||||
|
//随机码写入redis
|
||||||
|
var db = redis.GetDatabase(DbIndex);
|
||||||
|
bool redisSuccess = await db.StringSetAsync(email,code,TimeSpan.FromHours(1));
|
||||||
|
if (!redisSuccess)
|
||||||
|
{
|
||||||
|
throw new BaseException(1005,"Redis Str Set Error");
|
||||||
|
}
|
||||||
|
//发送邮件
|
||||||
|
await emailService.SendEmailAsync(email,subject,body);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
49
Apimanager_backend/Services/EmailSerivce.cs
Normal file
49
Apimanager_backend/Services/EmailSerivce.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using Apimanager_backend.Exceptions;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Mail;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Services
|
||||||
|
{
|
||||||
|
public class EmailService:IEmailService
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
public EmailService(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
SmtpHost = _configuration["EmailSettings:Server"];
|
||||||
|
Port = int.Parse(_configuration["EmailSettings:Port"]);
|
||||||
|
Username = _configuration["EmailSettings:Username"];
|
||||||
|
Password = _configuration["EmailSettings:Password"];
|
||||||
|
EnableSSL = bool.Parse(_configuration["EmailSettings:Ssl"]);
|
||||||
|
}
|
||||||
|
private string SmtpHost { get; set; }
|
||||||
|
private int Port { get; set; }
|
||||||
|
public bool EnableSSL { get; set; }
|
||||||
|
private string Username { get; set; }
|
||||||
|
private string Password { get; set; }
|
||||||
|
public async Task SendEmailAsync(string toEmail,string subject,string body)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using SmtpClient smtpClient = new SmtpClient(SmtpHost, Port)
|
||||||
|
{
|
||||||
|
Credentials = new NetworkCredential(Username, Password),
|
||||||
|
EnableSsl = EnableSSL, //启用ssl
|
||||||
|
Timeout = 30000
|
||||||
|
};
|
||||||
|
using var emailMessage = new MailMessage
|
||||||
|
{
|
||||||
|
From = new MailAddress(Username),
|
||||||
|
Subject = subject,
|
||||||
|
Body = body,
|
||||||
|
IsBodyHtml = true
|
||||||
|
};
|
||||||
|
emailMessage.To.Add(toEmail);
|
||||||
|
await smtpClient.SendMailAsync(emailMessage);
|
||||||
|
}catch(Exception e)
|
||||||
|
{
|
||||||
|
throw new BaseException(5004,e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Apimanager_backend/Services/IAdminService.cs
Normal file
45
Apimanager_backend/Services/IAdminService.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using Apimanager_backend.Dtos;
|
||||||
|
|
||||||
|
namespace Apimanager_backend.Services
|
||||||
|
{
|
||||||
|
public interface IAdminService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 禁用用户,使其无法登录。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">要禁用的用户ID</param>
|
||||||
|
/// <returns>异步操作</returns>
|
||||||
|
Task BanUserAsync(int userId);
|
||||||
|
/// <summary>
|
||||||
|
/// 取消禁用用户,恢复登录权限。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">要取消禁用的用户ID</param>
|
||||||
|
/// <returns>异步操作</returns>
|
||||||
|
Task UnbanUserAsync(int userId);
|
||||||
|
/// <summary>
|
||||||
|
/// 获取分页的用户列表。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="page">要获取的页码,从1开始</param>
|
||||||
|
/// <param name="pageSize">每页的用户数量</param>
|
||||||
|
/// <param name="desc">是否按降序排序</param>
|
||||||
|
/// <returns>包含用户信息的 <see cref="List{UserInfoDto}"/></returns>
|
||||||
|
Task<List<UserInfoDto>> GetUsersAsync(int page, int pageSize, bool desc);
|
||||||
|
/// <summary>
|
||||||
|
/// 创建新用户。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">包含新用户信息的 <see cref="CreateUserDto"/></param>
|
||||||
|
/// <returns>创建成功的用户信息 <see cref="UserInfoDto"/></returns>
|
||||||
|
Task<UserInfoDto> CreateUserAsync(CreateUserDto user);
|
||||||
|
/// <summary>
|
||||||
|
/// 删除指定的用户。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">用户ID</param>
|
||||||
|
/// <returns>异步操作</returns>
|
||||||
|
Task DeleteUserAsync(int userId);
|
||||||
|
/// <summary>
|
||||||
|
/// 修改用户信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<UserInfoDto> UpdateUserAsync(int userId,AdminUpdateUserDto dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,5 +11,17 @@ namespace Apimanager_backend.Services
|
|||||||
/// <param name="password">密码</param>
|
/// <param name="password">密码</param>
|
||||||
/// <returns>包含用户信息的 <see cref="UserInfoBaseDto"/></returns>
|
/// <returns>包含用户信息的 <see cref="UserInfoBaseDto"/></returns>
|
||||||
Task<UserInfoDto> LoginAsync(string username, string password);
|
Task<UserInfoDto> LoginAsync(string username, string password);
|
||||||
|
/// <summary>
|
||||||
|
/// 用户注册邮箱验证码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SendRegisterCodeAsync(string email);
|
||||||
|
/// <summary>
|
||||||
|
/// 用户注册
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<UserInfoDto> RegisterAsync(RegisterRequestDto dto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
Apimanager_backend/Services/IEmailService.cs
Normal file
14
Apimanager_backend/Services/IEmailService.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace Apimanager_backend.Services
|
||||||
|
{
|
||||||
|
public interface IEmailService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 发送邮件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="toEmail">收件人邮箱</param>
|
||||||
|
/// <param name="subject">主题</param>
|
||||||
|
/// <param name="body">正文</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task SendEmailAsync(string toEmail,string subject,string body);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,18 +13,18 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="refreshToken">刷新令牌</param>
|
/// <param name="refreshToken">刷新令牌</param>
|
||||||
/// <returns>是否验证通过</returns>
|
/// <returns>是否验证通过</returns>
|
||||||
Task<string?> ValidateRefreshTokenAsync(string refreshToken);
|
Task<bool> ValidateRefreshTokenAsync(string userId,string refreshToken);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除刷新令牌
|
/// 删除刷新令牌
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="refreshToken">刷新令牌</param>
|
/// <param name="refreshToken">刷新令牌</param>
|
||||||
/// <returns>是否删除成功</returns>
|
/// <returns>是否删除成功</returns>
|
||||||
Task DeleterRefreshTokenAsync(string refreshToken);
|
Task DeleterRefreshTokenAsync(string userId);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更新刷新令牌有效期
|
/// 更新刷新令牌有效期
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="refreshToken">刷新令牌</param>
|
/// <param name="userId">用户id</param>
|
||||||
/// <returns>是否成功</returns>
|
/// <returns>是否成功</returns>
|
||||||
Task UpdateRefreshTokenAsync(string refreshToken);
|
Task UpdateRefreshTokenAsync(string userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,73 +6,46 @@ namespace Apimanager_backend.Services
|
|||||||
{
|
{
|
||||||
public interface IUserService
|
public interface IUserService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 发送密码重置邮件到指定邮箱。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email">用户注册的邮箱地址</param>
|
||||||
|
/// <returns>异步操作</returns>
|
||||||
|
Task SendResetPasswordEmailAsync(string email);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置用户密码,验证重置令牌的有效性并更新密码。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email">用户邮箱地址</param>
|
||||||
|
/// <param name="token">重置密码的令牌</param>
|
||||||
|
/// <param name="newPassword">新的密码</param>
|
||||||
|
/// <returns>异步操作</returns>
|
||||||
|
Task ResetPasswordAsync(string email, string code, string newPassword);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送密码重置邮件到指定邮箱。
|
/// 获取用户信息。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="email">用户注册的邮箱地址</param>
|
/// <param name="userId">用户ID</param>
|
||||||
/// <returns>异步操作</returns>
|
/// <returns>包含用户信息的 <see cref="UserInfoDto"/></returns>
|
||||||
Task SendResetPasswordEmailAsync(string email);
|
Task<UserInfoDto> GetUserAsync(int userId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 重置用户密码,验证重置令牌的有效性并更新密码。
|
/// 更新用户信息。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="email">用户邮箱地址</param>
|
/// <param name="user">包含更新信息的 <see cref="UpdateUserDto"/></param>
|
||||||
/// <param name="token">重置密码的令牌</param>
|
/// <returns>更新后的 <see cref="UserInfoDto"/></returns>
|
||||||
/// <param name="newPassword">新的密码</param>
|
Task<UserInfoDto> UpdateUserAsync(int userId,UpdateUserDto user);
|
||||||
/// <returns>异步操作</returns>
|
/// <summary>
|
||||||
Task ResetPasswordAsync(string email, string token, string newPassword);
|
/// 检测用户名是否被使用
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
/// <param name="username">用户名</param>
|
||||||
/// 获取用户信息。
|
/// <returns></returns>
|
||||||
/// </summary>
|
Task<bool> IsUsernameExist(string username);
|
||||||
/// <param name="userId">用户ID</param>
|
/// <summary>
|
||||||
/// <returns>包含用户信息的 <see cref="UserInfoDto"/></returns>
|
/// 检测邮箱是否被使用
|
||||||
Task<UserInfoDto> GetUserAsync(int userId);
|
/// </summary>
|
||||||
|
/// <param name="email">邮箱</param>
|
||||||
/// <summary>
|
/// <returns></returns>
|
||||||
/// 更新用户信息。
|
Task<bool> IsEmailExist(string email);
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">包含更新信息的 <see cref="UpdateUserDto"/></param>
|
|
||||||
/// <returns>更新后的 <see cref="UserInfoDto"/></returns>
|
|
||||||
Task<UserInfoDto> UpdateUserAsync(UpdateUserDto user);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除指定的用户。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="username">要删除的用户名</param>
|
|
||||||
/// <returns>异步操作</returns>
|
|
||||||
Task DeleteUserAsync(string username);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建新用户。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">包含新用户信息的 <see cref="CreateUserDto"/></param>
|
|
||||||
/// <returns>创建成功的用户信息 <see cref="UserInfoDto"/></returns>
|
|
||||||
Task<UserInfoDto> CreateUserAsync(CreateUserDto user);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 禁用用户,使其无法登录。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="username">要禁用的用户名</param>
|
|
||||||
/// <returns>异步操作</returns>
|
|
||||||
Task BanUserAsync(string username);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取消禁用用户,恢复登录权限。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="username">要取消禁用的用户名</param>
|
|
||||||
/// <returns>异步操作</returns>
|
|
||||||
Task UnbanUserAsync(string username);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取分页的用户列表。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="page">要获取的页码,从1开始</param>
|
|
||||||
/// <param name="pageSize">每页的用户数量</param>
|
|
||||||
/// <param name="desc">是否按降序排序</param>
|
|
||||||
/// <returns>包含用户信息的 <see cref="List{UserInfoDto}"/></returns>
|
|
||||||
Task<List<UserInfoDto>> GetUsersAsync(int page, int pageSize, bool desc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,62 +7,72 @@ namespace Apimanager_backend.Services
|
|||||||
{
|
{
|
||||||
private readonly IConnectionMultiplexer redis;
|
private readonly IConnectionMultiplexer redis;
|
||||||
private readonly IConfiguration configuration;
|
private readonly IConfiguration configuration;
|
||||||
|
private readonly int DbIndex = 0;
|
||||||
public RefreshTokenService(IConnectionMultiplexer redis, IConfiguration configuration)
|
public RefreshTokenService(IConnectionMultiplexer redis, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
this.redis = redis;
|
this.redis = redis;
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
}
|
}
|
||||||
|
#region 创建刷新令牌
|
||||||
public async Task<string> CreateRefereshTokenAsync(string userId)
|
public async Task<string> CreateRefereshTokenAsync(string userId)
|
||||||
{
|
{
|
||||||
var refreshToken = Guid.NewGuid().ToString();
|
var refreshToken = Guid.NewGuid().ToString();
|
||||||
var expiryDays = Convert.ToDouble(configuration["JwtSettings:RefreshTokenExpiryDays"]);
|
var expiryDays = Convert.ToDouble(configuration["JwtSettings:RefreshTokenExpiryDays"]);
|
||||||
|
|
||||||
// 保存到Redis,设置过期时间
|
// 保存到Redis,设置过期时间
|
||||||
var db = redis.GetDatabase();
|
var db = redis.GetDatabase(DbIndex);
|
||||||
var res = await db.StringSetAsync(refreshToken, userId, TimeSpan.FromDays(expiryDays));
|
var res = await db.StringSetAsync( userId , refreshToken, TimeSpan.FromDays(expiryDays));
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
throw new BaseException(1006, "Service unavailable");
|
throw new BaseException(1006, "Service unavailable");
|
||||||
}
|
}
|
||||||
return refreshToken;
|
return refreshToken;
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
public async Task DeleterRefreshTokenAsync(string refreshToken)
|
#region 删除刷新令牌
|
||||||
|
public async Task DeleterRefreshTokenAsync(string userId)
|
||||||
{
|
{
|
||||||
var db = redis.GetDatabase();
|
var db = redis.GetDatabase(DbIndex);
|
||||||
bool res = await db.KeyDeleteAsync(refreshToken);
|
bool res = await db.KeyDeleteAsync(userId);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
throw new BaseException(1006, "Service unavailable");
|
throw new BaseException(1006, "Service unavailable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
public async Task UpdateRefreshTokenAsync(string refreshToken)
|
#region 刷新令牌有效期
|
||||||
|
public async Task UpdateRefreshTokenAsync(string userId)
|
||||||
{
|
{
|
||||||
var db = redis.GetDatabase();
|
var db = redis.GetDatabase(DbIndex);
|
||||||
var expiryDays = Convert.ToDouble(configuration["JwtSettings:RefreshTokenExpiryDays"]);
|
var expiryDays = Convert.ToDouble(configuration["JwtSettings:RefreshTokenExpiryDays"]);
|
||||||
//获取refresh剩余有效时间
|
//获取refresh剩余有效时间
|
||||||
var time =await db.KeyTimeToLiveAsync(refreshToken);
|
var time =await db.KeyTimeToLiveAsync(userId);
|
||||||
//判断有效时间是否大于零天小于三天,否则不刷新有效期
|
//判断有效时间是否大于零天小于三天,否则不刷新有效期
|
||||||
if(time <= TimeSpan.Zero || time >= TimeSpan.FromDays(3))
|
if(time <= TimeSpan.Zero || time >= TimeSpan.FromDays(3))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//刷新过期时间
|
//刷新过期时间
|
||||||
await db.KeyExpireAsync(refreshToken,TimeSpan.FromDays(expiryDays));
|
await db.KeyExpireAsync(userId,TimeSpan.FromDays(expiryDays));
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
public async Task<string?> ValidateRefreshTokenAsync(string refreshToken)
|
#region 验证令牌
|
||||||
|
public async Task<bool> ValidateRefreshTokenAsync(string userId,string refreshToken)
|
||||||
{
|
{
|
||||||
var db = redis.GetDatabase();
|
var db = redis.GetDatabase(DbIndex);
|
||||||
var redisValue = await db.StringGetAsync(refreshToken);
|
var redisValue = await db.StringGetAsync(userId);
|
||||||
//验证refreshToken是否存在
|
//验证refreshToken是否存在
|
||||||
if (!redisValue.HasValue)
|
if (!redisValue.HasValue)
|
||||||
{
|
{
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
return redisValue.ToString();
|
string refreshTokenTrue = redisValue.ToString();
|
||||||
|
if (!refreshToken.Equals(refreshTokenTrue))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,12 @@ using Apimanager_backend.Data;
|
|||||||
using Apimanager_backend.Dtos;
|
using Apimanager_backend.Dtos;
|
||||||
using Apimanager_backend.Exceptions;
|
using Apimanager_backend.Exceptions;
|
||||||
using Apimanager_backend.Models;
|
using Apimanager_backend.Models;
|
||||||
|
using Apimanager_backend.Tools;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Microsoft.AspNetCore.Connections.Features;
|
using Microsoft.AspNetCore.Connections.Features;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
|
using StackExchange.Redis;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace Apimanager_backend.Services
|
namespace Apimanager_backend.Services
|
||||||
@ -14,26 +17,18 @@ namespace Apimanager_backend.Services
|
|||||||
{
|
{
|
||||||
private readonly ApiContext apiContext;
|
private readonly ApiContext apiContext;
|
||||||
private readonly IMapper mapper;
|
private readonly IMapper mapper;
|
||||||
public UserService(ApiContext apiContext,IMapper automapper)
|
private readonly ILogger<IUserService> logger;
|
||||||
|
private readonly IConnectionMultiplexer redis;
|
||||||
|
private readonly IEmailService emailService;
|
||||||
|
private readonly int DbSet = 2;
|
||||||
|
public UserService(ApiContext apiContext,IMapper automapper,ILogger<IUserService> logger,IConnectionMultiplexer redis,IEmailService emailService)
|
||||||
{
|
{
|
||||||
this.apiContext = apiContext;
|
this.apiContext = apiContext;
|
||||||
this.mapper = automapper;
|
this.mapper = automapper;
|
||||||
|
this.logger = logger;
|
||||||
|
this.redis = redis;
|
||||||
|
this.emailService = emailService;
|
||||||
}
|
}
|
||||||
public Task BanUserAsync(string username)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<UserInfoDto> CreateUserAsync(CreateUserDto user)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task DeleteUserAsync(string username)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<UserInfoDto> GetUserAsync(int userId)
|
public async Task<UserInfoDto> GetUserAsync(int userId)
|
||||||
{
|
{
|
||||||
User? user = await apiContext.Users.SingleOrDefaultAsync(x => x.Id == userId);
|
User? user = await apiContext.Users.SingleOrDefaultAsync(x => x.Id == userId);
|
||||||
@ -45,30 +40,66 @@ namespace Apimanager_backend.Services
|
|||||||
return mapper.Map<UserInfoDto>(user);
|
return mapper.Map<UserInfoDto>(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<UserInfoDto>> GetUsersAsync(int page, int pageSize, bool desc)
|
public async Task<bool> IsEmailExist(string email)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return await apiContext.Users.AnyAsync(x => x.Email == email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsUsernameExist(string username)
|
||||||
public Task ResetPasswordAsync(string email, string token, string newPassword)
|
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return await apiContext.Users.AnyAsync(x => x.Username == username);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SendResetPasswordEmailAsync(string email)
|
public async Task ResetPasswordAsync(string email, string code, string newPassword)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
//校验验证码
|
||||||
|
var db = redis.GetDatabase(DbSet);
|
||||||
|
var value = await db.StringGetAsync(email);
|
||||||
|
if (!value.HasValue || value.ToString() != code)
|
||||||
|
{
|
||||||
|
throw new BaseException(5005, "验证码错误");
|
||||||
|
}
|
||||||
|
//验证成功,开始重置流程
|
||||||
|
var user = await apiContext.Users.FirstOrDefaultAsync(x => x.Email == email);
|
||||||
|
if(user == null)
|
||||||
|
{
|
||||||
|
throw new BaseException(2004, "用户不存在");
|
||||||
|
}
|
||||||
|
//修改密码
|
||||||
|
user.PassHash = newPassword;
|
||||||
|
apiContext.Users.Update(user);
|
||||||
|
await apiContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
#region 发送密码重置邮件
|
||||||
public Task UnbanUserAsync(string username)
|
public async Task SendResetPasswordEmailAsync(string email)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var randomCode = RandomCodeHelper.GetRandomCodeStr();
|
||||||
|
//记录到redis
|
||||||
|
var db = redis.GetDatabase(DbSet);
|
||||||
|
bool redisSuccess = await db.StringSetAsync(email,randomCode,TimeSpan.FromHours(1));
|
||||||
|
if (!redisSuccess)
|
||||||
|
{
|
||||||
|
throw new BaseException(1005, "Redis Str Set Error");
|
||||||
|
}
|
||||||
|
string subject = "重置验证码";
|
||||||
|
string body = $"您的重置验证码为:{randomCode}<br>有效期60分钟!";
|
||||||
|
//发送邮件
|
||||||
|
await emailService.SendEmailAsync(email,subject,body);
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public Task<UserInfoDto> UpdateUserAsync(UpdateUserDto user)
|
public async Task<UserInfoDto> UpdateUserAsync(int userId,UpdateUserDto dto)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var user = await apiContext.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new BaseException(2004, "用户不存在");
|
||||||
|
}
|
||||||
|
user.PassHash = dto.password == null ? user.PassHash : dto.password;
|
||||||
|
|
||||||
|
apiContext.Users.Update(user);
|
||||||
|
await apiContext.SaveChangesAsync();
|
||||||
|
return mapper.Map<UserInfoDto>(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
Apimanager_backend/Tools/RandomCodeHelper.cs
Normal file
15
Apimanager_backend/Tools/RandomCodeHelper.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Apimanager_backend.Tools
|
||||||
|
{
|
||||||
|
public static class RandomCodeHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 生成随机数字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetRandomCodeStr()
|
||||||
|
{
|
||||||
|
Random random = new Random();
|
||||||
|
return random.Next(10000, 99999).ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
133
Apimanager_backend/Tools/StatusCodeHelper.cs
Normal file
133
Apimanager_backend/Tools/StatusCodeHelper.cs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
namespace Apimanager_backend.Tools
|
||||||
|
{
|
||||||
|
public static class StatusCodeHelper
|
||||||
|
{
|
||||||
|
public static int GetHttpStatusCode(int customErrorCode)
|
||||||
|
{
|
||||||
|
int httpStatusCode;
|
||||||
|
|
||||||
|
switch (customErrorCode)
|
||||||
|
{
|
||||||
|
// 通用错误码
|
||||||
|
case 1000: // 成功
|
||||||
|
httpStatusCode = 200;
|
||||||
|
break;
|
||||||
|
case 1001: // 参数错误
|
||||||
|
httpStatusCode = 400;
|
||||||
|
break;
|
||||||
|
case 1002: // 用户未登录或认证失败
|
||||||
|
httpStatusCode = 401;
|
||||||
|
break;
|
||||||
|
case 1003: // 无权限访问
|
||||||
|
httpStatusCode = 403;
|
||||||
|
break;
|
||||||
|
case 1004: // 资源未找到
|
||||||
|
httpStatusCode = 404;
|
||||||
|
break;
|
||||||
|
case 1005: // 服务器内部错误
|
||||||
|
httpStatusCode = 500;
|
||||||
|
break;
|
||||||
|
case 1006: // 服务暂时不可用
|
||||||
|
httpStatusCode = 503;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 用户模块错误码
|
||||||
|
case 2000: // 登录成功
|
||||||
|
httpStatusCode = 200;
|
||||||
|
break;
|
||||||
|
case 2001: // 用户名或密码错误
|
||||||
|
httpStatusCode = 401;
|
||||||
|
break;
|
||||||
|
case 2002: // 用户账户被禁用
|
||||||
|
httpStatusCode = 401;
|
||||||
|
break;
|
||||||
|
case 2003: // 用户名已存在
|
||||||
|
httpStatusCode = 409;
|
||||||
|
break;
|
||||||
|
case 2004: // 用户不存在
|
||||||
|
httpStatusCode = 404;
|
||||||
|
break;
|
||||||
|
case 2005: // 邮箱已存在
|
||||||
|
httpStatusCode = 409;
|
||||||
|
break;
|
||||||
|
case 2006: // 用户无权限进行该操作
|
||||||
|
httpStatusCode = 403;
|
||||||
|
break;
|
||||||
|
case 2007: // 密码重置失败
|
||||||
|
httpStatusCode = 400;
|
||||||
|
break;
|
||||||
|
case 2008: // 凭证到期或无效
|
||||||
|
httpStatusCode = 403;
|
||||||
|
break;
|
||||||
|
case 2009: // 刷新令牌到期或无效
|
||||||
|
httpStatusCode = 403;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// API模块错误码
|
||||||
|
case 3000: // API调用成功
|
||||||
|
httpStatusCode = 200;
|
||||||
|
break;
|
||||||
|
case 3001: // API访问受限
|
||||||
|
httpStatusCode = 403;
|
||||||
|
break;
|
||||||
|
case 3002: // API不存在
|
||||||
|
httpStatusCode = 404;
|
||||||
|
break;
|
||||||
|
case 3003: // API调用次数超限
|
||||||
|
httpStatusCode = 429;
|
||||||
|
break;
|
||||||
|
case 3004: // 未购买该API套餐或权限不足
|
||||||
|
httpStatusCode = 403;
|
||||||
|
break;
|
||||||
|
case 3005: // API调用失败,服务器错误
|
||||||
|
httpStatusCode = 500;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 套餐与支付模块错误码
|
||||||
|
case 4000: // 支付成功
|
||||||
|
httpStatusCode = 200;
|
||||||
|
break;
|
||||||
|
case 4001: // 支付请求无效
|
||||||
|
httpStatusCode = 400;
|
||||||
|
break;
|
||||||
|
case 4002: // 支付失败,余额不足
|
||||||
|
httpStatusCode = 402;
|
||||||
|
break;
|
||||||
|
case 4003: // 订单未找到
|
||||||
|
httpStatusCode = 404;
|
||||||
|
break;
|
||||||
|
case 4004: // 重复支付或订单冲突
|
||||||
|
httpStatusCode = 409;
|
||||||
|
break;
|
||||||
|
case 4005: // 支付系统错误
|
||||||
|
httpStatusCode = 500;
|
||||||
|
break;
|
||||||
|
case 4006: // 退款成功
|
||||||
|
httpStatusCode = 200;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 日志与系统模块错误码
|
||||||
|
case 5000: // 日志查询成功
|
||||||
|
httpStatusCode = 200;
|
||||||
|
break;
|
||||||
|
case 5001: // 日志记录未找到
|
||||||
|
httpStatusCode = 404;
|
||||||
|
break;
|
||||||
|
case 5002: // 日志服务异常
|
||||||
|
httpStatusCode = 500;
|
||||||
|
break;
|
||||||
|
case 5003: // 无权限查看操作日志
|
||||||
|
httpStatusCode = 403;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// 未知错误码,返回 500
|
||||||
|
httpStatusCode = 500;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpStatusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,5 +18,12 @@
|
|||||||
},
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
"ConnectionString": "192.168.5.200:6379"
|
"ConnectionString": "192.168.5.200:6379"
|
||||||
|
},
|
||||||
|
"EmailSettings": {
|
||||||
|
"Server": "smtp.exmail.qq.com",
|
||||||
|
"Port": "587",
|
||||||
|
"Ssl": true,
|
||||||
|
"Username": "nanxun@nxsir.cn",
|
||||||
|
"Password": "2919054393Dyw"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,3 +58,5 @@
|
|||||||
| 5001 | 404 | 日志记录未找到 | Log record not found |
|
| 5001 | 404 | 日志记录未找到 | Log record not found |
|
||||||
| 5002 | 500 | 日志服务异常 | Log service error |
|
| 5002 | 500 | 日志服务异常 | Log service error |
|
||||||
| 5003 | 403 | 无权限查看操作日志 | No permission to view logs |
|
| 5003 | 403 | 无权限查看操作日志 | No permission to view logs |
|
||||||
|
| 5004 | 500 | 邮件发送错误 | Email send error |
|
||||||
|
| 5005 | 400 | 验证码错误 | ValidateCode Error |
|
||||||
Loading…
Reference in New Issue
Block a user