diff --git a/Apimanager_backend/Apimanager_backend.csproj b/Apimanager_backend/Apimanager_backend.csproj index ce65827..2d17395 100644 --- a/Apimanager_backend/Apimanager_backend.csproj +++ b/Apimanager_backend/Apimanager_backend.csproj @@ -7,6 +7,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -16,10 +17,7 @@ - - - diff --git a/Apimanager_backend/Config/MyAutomapper.cs b/Apimanager_backend/Config/MyAutomapper.cs new file mode 100644 index 0000000..159ff8c --- /dev/null +++ b/Apimanager_backend/Config/MyAutomapper.cs @@ -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(); + } + } +} diff --git a/Apimanager_backend/Config/ServiceCollectionExtensions.cs b/Apimanager_backend/Config/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..28a5528 --- /dev/null +++ b/Apimanager_backend/Config/ServiceCollectionExtensions.cs @@ -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(); + return services; + } + } +} diff --git a/Apimanager_backend/Controllers/UserController.cs b/Apimanager_backend/Controllers/UserController.cs new file mode 100644 index 0000000..268d1ef --- /dev/null +++ b/Apimanager_backend/Controllers/UserController.cs @@ -0,0 +1,51 @@ +using Apimanager_backend.Dtos; +using Apimanager_backend.Exceptions; +using Apimanager_backend.Services; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Apimanager_backend.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class UserController : ControllerBase + { + private readonly IUserService userService; + public UserController(IUserService userService) + { + this.userService = userService; + } + /// + /// 用户登录控制器 + /// + /// 登录信息 + /// 通用返回信息格式 + [HttpPost("Login")] + public async Task>> Login([FromBody]UserLoginDto dto) + { + try + { + UserInfoDto user = await userService.LoginAsync(dto.UserName, dto.Password); + + var responseInfo = new ResponseBase( + code: 2000, + message: "Login successful", + data: user + ); + return Ok(responseInfo); + } + catch (BaseException e) + { + + //错误时,构建错误信息对象 + var responseInfo = new ResponseBase( + code:e.code, + message: e.message, + data: null + ); + + return Unauthorized(responseInfo); + } + } + } +} diff --git a/Apimanager_backend/Data/ApiContext.cs b/Apimanager_backend/Data/ApiContext.cs index 1be7614..9038552 100644 --- a/Apimanager_backend/Data/ApiContext.cs +++ b/Apimanager_backend/Data/ApiContext.cs @@ -24,6 +24,9 @@ namespace Apimanager_backend.Data protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApiContext).Assembly); + // 配置全局查询筛选器 + modelBuilder.Entity().HasQueryFilter(u => !u.IsDelete); + modelBuilder.Entity().HasQueryFilter(a => !a.IsDelete); } } diff --git a/Apimanager_backend/Dtos/CreateUserDto.cs b/Apimanager_backend/Dtos/CreateUserDto.cs new file mode 100644 index 0000000..9c8b9d2 --- /dev/null +++ b/Apimanager_backend/Dtos/CreateUserDto.cs @@ -0,0 +1,6 @@ +namespace Apimanager_backend.Dtos +{ + public class CreateUserDto + { + } +} diff --git a/Apimanager_backend/Dtos/ResponseBase.cs b/Apimanager_backend/Dtos/ResponseBase.cs new file mode 100644 index 0000000..94d94f9 --- /dev/null +++ b/Apimanager_backend/Dtos/ResponseBase.cs @@ -0,0 +1,20 @@ +namespace Apimanager_backend.Dtos +{ + /// + /// 响应基类,构造最后的返回结果 + /// + /// 返回的具体数据类型 + public class ResponseBase + { + 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() { } + } +} diff --git a/Apimanager_backend/Dtos/UpdateUserDto.cs b/Apimanager_backend/Dtos/UpdateUserDto.cs new file mode 100644 index 0000000..3c53eed --- /dev/null +++ b/Apimanager_backend/Dtos/UpdateUserDto.cs @@ -0,0 +1,6 @@ +namespace Apimanager_backend.Dtos +{ + public class UpdateUserDto + { + } +} diff --git a/Apimanager_backend/Dtos/UserInfoDto.cs b/Apimanager_backend/Dtos/UserInfoDto.cs new file mode 100644 index 0000000..927ffed --- /dev/null +++ b/Apimanager_backend/Dtos/UserInfoDto.cs @@ -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; } + } +} diff --git a/Apimanager_backend/Dtos/UserLoginDto.cs b/Apimanager_backend/Dtos/UserLoginDto.cs new file mode 100644 index 0000000..eaed324 --- /dev/null +++ b/Apimanager_backend/Dtos/UserLoginDto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace Apimanager_backend.Dtos +{ + public class UserLoginDto + { + [MaxLength(20)] + public string UserName { get; set; } + public string Password { get; set; } + } +} diff --git a/Apimanager_backend/Exceptions/BaseException.cs b/Apimanager_backend/Exceptions/BaseException.cs new file mode 100644 index 0000000..a75a609 --- /dev/null +++ b/Apimanager_backend/Exceptions/BaseException.cs @@ -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; + } + } +} diff --git a/Apimanager_backend/Program.cs b/Apimanager_backend/Program.cs index 8661d8a..ca41bc8 100644 --- a/Apimanager_backend/Program.cs +++ b/Apimanager_backend/Program.cs @@ -1,3 +1,4 @@ +using Apimanager_backend.Config; using Apimanager_backend.Data; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; @@ -15,7 +16,7 @@ string? constr = configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(option => option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr)) ); - +builder.Services.AddAllService(configuration); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/Apimanager_backend/Services/IUserService.cs b/Apimanager_backend/Services/IUserService.cs new file mode 100644 index 0000000..0d2212a --- /dev/null +++ b/Apimanager_backend/Services/IUserService.cs @@ -0,0 +1,84 @@ +using Apimanager_backend.Dtos; +using Apimanager_backend.Models; +using System.Runtime.CompilerServices; + +namespace Apimanager_backend.Services +{ + public interface IUserService + { + /// + /// 登录用户,根据用户名和密码进行身份验证。 + /// + /// 用户名 + /// 密码 + /// 包含用户信息的 + Task LoginAsync(string username, string password); + + /// + /// 发送密码重置邮件到指定邮箱。 + /// + /// 用户注册的邮箱地址 + /// 异步操作 + Task SendResetPasswordEmailAsync(string email); + + /// + /// 重置用户密码,验证重置令牌的有效性并更新密码。 + /// + /// 用户邮箱地址 + /// 重置密码的令牌 + /// 新的密码 + /// 异步操作 + Task ResetPasswordAsync(string email, string token, string newPassword); + + /// + /// 获取用户信息。 + /// + /// 用户名 + /// 包含用户信息的 + Task GetUserAsync(string username); + + /// + /// 更新用户信息。 + /// + /// 包含更新信息的 + /// 更新后的 + Task UpdateUserAsync(UpdateUserDto user); + + /// + /// 删除指定的用户。 + /// + /// 要删除的用户名 + /// 异步操作 + Task DeleteUserAsync(string username); + + /// + /// 创建新用户。 + /// + /// 包含新用户信息的 + /// 创建成功的用户信息 + Task CreateUserAsync(CreateUserDto user); + + /// + /// 禁用用户,使其无法登录。 + /// + /// 要禁用的用户名 + /// 异步操作 + Task BanUserAsync(string username); + + /// + /// 取消禁用用户,恢复登录权限。 + /// + /// 要取消禁用的用户名 + /// 异步操作 + Task UnbanUserAsync(string username); + + /// + /// 获取分页的用户列表。 + /// + /// 要获取的页码,从1开始 + /// 每页的用户数量 + /// 是否按降序排序 + /// 包含用户信息的 + Task> GetUsersAsync(int page, int pageSize, bool desc); + } +} diff --git a/Apimanager_backend/Services/UserService.cs b/Apimanager_backend/Services/UserService.cs new file mode 100644 index 0000000..c6859a7 --- /dev/null +++ b/Apimanager_backend/Services/UserService.cs @@ -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 CreateUserAsync(CreateUserDto user) + { + throw new NotImplementedException(); + } + + public Task DeleteUserAsync(string username) + { + throw new NotImplementedException(); + } + + public Task GetUserAsync(string username) + { + throw new NotImplementedException(); + } + + public Task> GetUsersAsync(int page, int pageSize, bool desc) + { + throw new NotImplementedException(); + } + + public async Task 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(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 UpdateUserAsync(UpdateUserDto user) + { + throw new NotImplementedException(); + } + } +} diff --git a/README.md b/README.md index e83113f..44be4e1 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,4 @@ api-billing-system/ - [x] 数据库文档 **Database.md** - [x] 错误码文档 **ErrorCode.md** - [x] API定义文档 **APIDefine.md** -- [ ] API文档 **[Apifox - 接口文档分享](https://apifox.com/apidoc/shared-8730c2eb-595b-4cf4-941d-d58914d4cd1e)** \ No newline at end of file +- [ ] API文档 **[API文档](https://apifox.com/apidoc/shared-8730c2eb-595b-4cf4-941d-d58914d4cd1e)** \ No newline at end of file