Merge branch 'master_add_auth_1027' into 'master'
Master add auth 1027 See merge request ql/apismnagaer_backend!6
This commit is contained in:
commit
4f904441ac
@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@ -16,10 +17,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Controllers\" />
|
||||
<Folder Include="Services\" />
|
||||
<Folder Include="Tools\" />
|
||||
<Folder Include="Config\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
14
Apimanager_backend/Config/MyAutomapper.cs
Normal file
14
Apimanager_backend/Config/MyAutomapper.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using Apimanager_backend.Dtos;
|
||||
using Apimanager_backend.Models;
|
||||
using AutoMapper;
|
||||
|
||||
namespace Apimanager_backend.Config
|
||||
{
|
||||
public class MyAutomapper:Profile
|
||||
{
|
||||
public MyAutomapper()
|
||||
{
|
||||
CreateMap<User,UserInfoDto>();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Apimanager_backend/Config/ServiceCollectionExtensions.cs
Normal file
15
Apimanager_backend/Config/ServiceCollectionExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Apimanager_backend.Services;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Apimanager_backend.Config
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddAllService(this IServiceCollection services,IConfiguration configuration)
|
||||
{
|
||||
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Apimanager_backend/Controllers/UserController.cs
Normal file
53
Apimanager_backend/Controllers/UserController.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using Apimanager_backend.Dtos;
|
||||
using Apimanager_backend.Exceptions;
|
||||
using Apimanager_backend.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Apimanager_backend.Filters;
|
||||
|
||||
namespace Apimanager_backend.Controllers
|
||||
{
|
||||
[ModelValidationFilter()]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private readonly IUserService userService;
|
||||
public UserController(IUserService userService)
|
||||
{
|
||||
this.userService = userService;
|
||||
}
|
||||
/// <summary>
|
||||
/// 用户登录控制器
|
||||
/// </summary>
|
||||
/// <param name="dto">登录信息</param>
|
||||
/// <returns>通用返回信息格式</returns>
|
||||
[HttpPost("Login")]
|
||||
public async Task<ActionResult<ResponseBase<UserInfoDto>>> Login([FromBody]UserLoginDto dto)
|
||||
{
|
||||
try
|
||||
{
|
||||
UserInfoDto user = await userService.LoginAsync(dto.UserName, dto.Password);
|
||||
|
||||
var responseInfo = new ResponseBase<UserInfoDto>(
|
||||
code: 2000,
|
||||
message: "Login successful",
|
||||
data: user
|
||||
);
|
||||
return Ok(responseInfo);
|
||||
}
|
||||
catch (BaseException e)
|
||||
{
|
||||
|
||||
//错误时,构建错误信息对象
|
||||
var responseInfo = new ResponseBase<object?>(
|
||||
code:e.code,
|
||||
message: e.message,
|
||||
data: null
|
||||
);
|
||||
|
||||
return Unauthorized(responseInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,9 @@ namespace Apimanager_backend.Data
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApiContext).Assembly);
|
||||
// 配置全局查询筛选器
|
||||
modelBuilder.Entity<User>().HasQueryFilter(u => !u.IsDelete);
|
||||
modelBuilder.Entity<Api>().HasQueryFilter(a => !a.IsDelete);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
6
Apimanager_backend/Dtos/CreateUserDto.cs
Normal file
6
Apimanager_backend/Dtos/CreateUserDto.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Apimanager_backend.Dtos
|
||||
{
|
||||
public class CreateUserDto
|
||||
{
|
||||
}
|
||||
}
|
||||
20
Apimanager_backend/Dtos/ResponseBase.cs
Normal file
20
Apimanager_backend/Dtos/ResponseBase.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace Apimanager_backend.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// 响应基类,构造最后的返回结果
|
||||
/// </summary>
|
||||
/// <typeparam name="T">返回的具体数据类型</typeparam>
|
||||
public class ResponseBase<T>
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public string Message { get; set; }
|
||||
public T? Data { get; set; }
|
||||
public ResponseBase(int code,string message,T data)
|
||||
{
|
||||
this.Code = code;
|
||||
this.Message = message;
|
||||
this.Data = data;
|
||||
}
|
||||
public ResponseBase() { }
|
||||
}
|
||||
}
|
||||
6
Apimanager_backend/Dtos/UpdateUserDto.cs
Normal file
6
Apimanager_backend/Dtos/UpdateUserDto.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Apimanager_backend.Dtos
|
||||
{
|
||||
public class UpdateUserDto
|
||||
{
|
||||
}
|
||||
}
|
||||
15
Apimanager_backend/Dtos/UserInfoDto.cs
Normal file
15
Apimanager_backend/Dtos/UserInfoDto.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Apimanager_backend.Models;
|
||||
|
||||
namespace Apimanager_backend.Dtos
|
||||
{
|
||||
public class UserInfoDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string UserName { get; set; }
|
||||
public string Email { get; set; }
|
||||
public UserRole Role { get; set; }
|
||||
public bool IsBan { get; set; }
|
||||
public decimal Balance { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
}
|
||||
}
|
||||
13
Apimanager_backend/Dtos/UserLoginDto.cs
Normal file
13
Apimanager_backend/Dtos/UserLoginDto.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Apimanager_backend.Dtos
|
||||
{
|
||||
public class UserLoginDto
|
||||
{
|
||||
[MaxLength(20,ErrorMessage = "The maximum username is 20 characters")]
|
||||
public string UserName { get; set; }
|
||||
[MaxLength(50,ErrorMessage = "The maximum password is 50 characters")]
|
||||
[Required(ErrorMessage = "password is required")]
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
13
Apimanager_backend/Exceptions/BaseException.cs
Normal file
13
Apimanager_backend/Exceptions/BaseException.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Apimanager_backend.Exceptions
|
||||
{
|
||||
public class BaseException:Exception
|
||||
{
|
||||
public int code;
|
||||
public string message;
|
||||
public BaseException(int code, string message):base(message)
|
||||
{
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Apimanager_backend/Filters/ModelValidationFilter.cs
Normal file
34
Apimanager_backend/Filters/ModelValidationFilter.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using Apimanager_backend.Dtos;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Apimanager_backend.Filters
|
||||
{
|
||||
public class ModelValidationFilter : Attribute,IActionFilter
|
||||
{
|
||||
public void OnActionExecuted(ActionExecutedContext context) { }
|
||||
|
||||
public void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
// 将所有的错误信息收集到列表中
|
||||
var errors = context.ModelState.Values
|
||||
.SelectMany(v => v.Errors)
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToList();
|
||||
|
||||
// 构造统一的响应格式
|
||||
var response = new ResponseBase<object?>
|
||||
{
|
||||
Code = 1001, // 统一的错误码
|
||||
Message = errors[0],
|
||||
Data = null
|
||||
};
|
||||
|
||||
// 设置错误响应和 HTTP 状态码
|
||||
context.Result = new BadRequestObjectResult(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
using Apimanager_backend.Config;
|
||||
using Apimanager_backend.Data;
|
||||
using Apimanager_backend.Filters;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@ -15,8 +17,11 @@ string? constr = configuration.GetConnectionString("DefaultConnection");
|
||||
builder.Services.AddDbContext<ApiContext>(option =>
|
||||
option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr))
|
||||
);
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddAllService(configuration);
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
options.Filters.Add<ModelValidationFilter>();
|
||||
});
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
84
Apimanager_backend/Services/IUserService.cs
Normal file
84
Apimanager_backend/Services/IUserService.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using Apimanager_backend.Dtos;
|
||||
using Apimanager_backend.Models;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Apimanager_backend.Services
|
||||
{
|
||||
public interface IUserService
|
||||
{
|
||||
/// <summary>
|
||||
/// 登录用户,根据用户名和密码进行身份验证。
|
||||
/// </summary>
|
||||
/// <param name="username">用户名</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <returns>包含用户信息的 <see cref="UserInfoDto"/></returns>
|
||||
Task<UserInfoDto> LoginAsync(string username, string password);
|
||||
|
||||
/// <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 token, string newPassword);
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户信息。
|
||||
/// </summary>
|
||||
/// <param name="username">用户名</param>
|
||||
/// <returns>包含用户信息的 <see cref="UserInfoDto"/></returns>
|
||||
Task<UserInfoDto> GetUserAsync(string username);
|
||||
|
||||
/// <summary>
|
||||
/// 更新用户信息。
|
||||
/// </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);
|
||||
}
|
||||
}
|
||||
89
Apimanager_backend/Services/UserService.cs
Normal file
89
Apimanager_backend/Services/UserService.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using Apimanager_backend.Config;
|
||||
using Apimanager_backend.Data;
|
||||
using Apimanager_backend.Dtos;
|
||||
using Apimanager_backend.Exceptions;
|
||||
using Apimanager_backend.Models;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Apimanager_backend.Services
|
||||
{
|
||||
public class UserService : IUserService
|
||||
{
|
||||
private readonly ApiContext apiContext;
|
||||
private readonly IMapper mapper;
|
||||
public UserService(ApiContext apiContext,IMapper automapper)
|
||||
{
|
||||
this.apiContext = apiContext;
|
||||
this.mapper = automapper;
|
||||
}
|
||||
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 Task<UserInfoDto> GetUserAsync(string username)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<List<UserInfoDto>> GetUsersAsync(int page, int pageSize, bool desc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<UserInfoDto> LoginAsync(string username, string password)
|
||||
{
|
||||
//查找用户
|
||||
User? user = await apiContext.Users.SingleOrDefaultAsync(x =>
|
||||
x.Username == username && x.PassHash == password
|
||||
);
|
||||
|
||||
//用户不存在或密码错误都为登录失败
|
||||
if(user == null)
|
||||
{
|
||||
throw new BaseException(2001, "Invalid username or password");
|
||||
}
|
||||
|
||||
//用户被禁用
|
||||
if (user.IsBan)
|
||||
{
|
||||
throw new BaseException(2002, "User account is disabled");
|
||||
}
|
||||
|
||||
return mapper.Map<UserInfoDto>(user);
|
||||
}
|
||||
|
||||
public Task ResetPasswordAsync(string email, string token, string newPassword)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SendResetPasswordEmailAsync(string email)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UnbanUserAsync(string username)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<UserInfoDto> UpdateUserAsync(UpdateUserDto user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user