Merge pull request 'feature-nxdev' (#20) from feature-nxdev into main
Reviewed-on: #20
This commit is contained in:
commit
4c7bdbe9fc
@ -9,6 +9,23 @@ namespace IM_API.Configs
|
||||
public MapperConfig()
|
||||
{
|
||||
CreateMap<User, UserInfoDto>();
|
||||
//用户信息更新模型转换
|
||||
CreateMap<UpdateUserDto, User>()
|
||||
.ForMember(dest => dest.Updated,opt => opt.MapFrom(src => DateTime.Now))
|
||||
.ForAllMembers(opts => opts.Condition((src,dest,srcMember) => srcMember != null));
|
||||
//用户注册模型转换
|
||||
CreateMap<RegisterRequestDto, User>()
|
||||
.ForMember(dest => dest.Username,opt => opt.MapFrom(src => src.Username))
|
||||
.ForMember(dest => dest.Password,opt => opt.MapFrom(src => src.Password))
|
||||
.ForMember(dest => dest.Avatar,opt => opt.MapFrom(src => "https://ts1.tc.mm.bing.net/th/id/OIP-C.dl0WpkTP6E2J4FnhDC_jHwAAAA?rs=1&pid=ImgDetMain&o=7&rm=3"))
|
||||
.ForMember(dest => dest.StatusEnum,opt => opt.MapFrom(src => UserStatus.Normal))
|
||||
.ForMember(dest => dest.OnlineStatusEnum,opt => opt.MapFrom(src => UserOnlineStatus.Offline))
|
||||
.ForMember(dest => dest.NickName,opt => opt.MapFrom(src => src.NickName))
|
||||
.ForMember(dest => dest.Created,opt => opt.MapFrom(src => DateTime.Now))
|
||||
.ForMember(dest => dest.IsDeleted,opt => opt.MapFrom(src => 0))
|
||||
;
|
||||
//好友信息模型转换
|
||||
CreateMap<Friend, FriendInfoDto>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ namespace IM_API.Configs
|
||||
{
|
||||
services.AddAutoMapper(typeof(MapperConfig));
|
||||
services.AddTransient<IAuthService, AuthService>();
|
||||
services.AddTransient<IUserService, UserService>();
|
||||
services.AddSingleton<IJWTService, JWTService>();
|
||||
services.AddSingleton<IRefreshTokenService,RedisRefreshTokenService>();
|
||||
return services;
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Interface.Services;
|
||||
using IM_API.Tools;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace IM_API.Controllers
|
||||
@ -11,16 +13,18 @@ namespace IM_API.Controllers
|
||||
{
|
||||
private readonly ILogger<AuthController> _logger;
|
||||
private readonly IAuthService _authService;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IJWTService _jwtService;
|
||||
private readonly IRefreshTokenService _refreshTokenService;
|
||||
private readonly IConfiguration _configuration;
|
||||
public AuthController(ILogger<AuthController> logger, IAuthService authService, IJWTService jwtService, IRefreshTokenService refreshTokenService, IConfiguration configuration)
|
||||
public AuthController(ILogger<AuthController> logger, IAuthService authService, IJWTService jwtService, IRefreshTokenService refreshTokenService, IConfiguration configuration,IUserService userService)
|
||||
{
|
||||
_logger = logger;
|
||||
_authService = authService;
|
||||
_jwtService = jwtService;
|
||||
_refreshTokenService = refreshTokenService;
|
||||
_configuration = configuration;
|
||||
_userService = userService;
|
||||
}
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Login(LoginRequestDto dto)
|
||||
@ -33,5 +37,26 @@ namespace IM_API.Controllers
|
||||
var res = new BaseResponse<LoginDto>(new LoginDto(user.Id,token,refreshToken,expiresAt));
|
||||
return Ok(res);
|
||||
}
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Register(RegisterRequestDto dto)
|
||||
{
|
||||
var userInfo = await _authService.RegisterAsync(dto);
|
||||
var res = new BaseResponse<UserInfoDto>(userInfo);
|
||||
return Ok(res);
|
||||
}
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Refresh(RefreshDto dto)
|
||||
{
|
||||
(bool ok,int userId) = await _refreshTokenService.ValidateRefreshTokenAsync(dto.refreshToken);
|
||||
if (!ok)
|
||||
{
|
||||
var err = new BaseResponse<LoginDto>(CodeDefine.AUTH_FAILED);
|
||||
return Unauthorized(err);
|
||||
}
|
||||
var userinfo = await _userService.GetUserInfoAsync(userId);
|
||||
(string token,DateTime expiresAt) = _jwtService.CreateAccessTokenForUser(userinfo.Id,userinfo.Username,"user");
|
||||
var res = new BaseResponse<LoginDto>(new LoginDto(userinfo.Id,token,dto.refreshToken,expiresAt));
|
||||
return Ok(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
103
backend/IM_API/Controllers/UserController.cs
Normal file
103
backend/IM_API/Controllers/UserController.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Interface.Services;
|
||||
using IM_API.Tools;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace IM_API.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly ILogger<UserController> _logger;
|
||||
public UserController(IUserService userService, ILogger<UserController> logger)
|
||||
{
|
||||
_userService = userService;
|
||||
_logger = logger;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取当前用户信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Me()
|
||||
{
|
||||
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
int userId = int.Parse(userIdStr);
|
||||
var userinfo = await _userService.GetUserInfoAsync(userId);
|
||||
var res = new BaseResponse<UserInfoDto>(userinfo);
|
||||
return Ok(res);
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改用户资料
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Profile(UpdateUserDto dto)
|
||||
{
|
||||
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
int userId = int.Parse(userIdStr);
|
||||
var userinfo = await _userService.UpdateUserAsync(userId,dto);
|
||||
var res = new BaseResponse<UserInfoDto>(userinfo);
|
||||
return Ok(res);
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// ID查询用户
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Find(int userId)
|
||||
{
|
||||
var userinfo = await _userService.GetUserInfoAsync(userId);
|
||||
var res = new BaseResponse<UserInfoDto>(userinfo);
|
||||
return Ok(res);
|
||||
}
|
||||
/// <summary>
|
||||
/// 用户名查询用户
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Find(string username)
|
||||
{
|
||||
var userinfo = await _userService.GetUserInfoByUsernameAsync(username);
|
||||
var res = new BaseResponse<UserInfoDto>(userinfo);
|
||||
return Ok(res);
|
||||
}
|
||||
/// <summary>
|
||||
/// 重置用户密码
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> ResetPassword(PasswordResetDto dto)
|
||||
{
|
||||
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
int userId = int.Parse(userIdStr);
|
||||
await _userService.ResetPasswordAsync(userId,dto.oldPassword,dto.Password);
|
||||
return Ok(new BaseResponse<object?>());
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置在线状态
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> SetOnlineStatus(OnlineStatusSetDto dto)
|
||||
{
|
||||
var userIdStr = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
int userId = int.Parse(userIdStr);
|
||||
await _userService.UpdateOlineStatusAsync(userId, dto.OnlineStatus);
|
||||
return Ok(new BaseResponse<object?>());
|
||||
}
|
||||
}
|
||||
}
|
||||
4
backend/IM_API/Dtos/AuthDto.cs
Normal file
4
backend/IM_API/Dtos/AuthDto.cs
Normal file
@ -0,0 +1,4 @@
|
||||
namespace IM_API.Dtos
|
||||
{
|
||||
public record RefreshDto(string refreshToken);
|
||||
}
|
||||
@ -64,6 +64,15 @@ namespace IM_API.Dtos
|
||||
Code = code;
|
||||
Message = message;
|
||||
}
|
||||
/// <summary>
|
||||
/// 接受codedefine对象
|
||||
/// </summary>
|
||||
/// <param name="codeDefine"></param>
|
||||
public BaseResponse(CodeDefine codeDefine)
|
||||
{
|
||||
this.Code = codeDefine.Code;
|
||||
this.Message = codeDefine.Message;
|
||||
}
|
||||
public BaseResponse() { }
|
||||
}
|
||||
}
|
||||
|
||||
6
backend/IM_API/Dtos/FriendDto.cs
Normal file
6
backend/IM_API/Dtos/FriendDto.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using IM_API.Models;
|
||||
|
||||
namespace IM_API.Dtos
|
||||
{
|
||||
public record FriendInfoDto(int Id, int UserId,int FriendId,FriendStatus StatusEnum,DateTime Created,string RemarkName,string? Avatar);
|
||||
}
|
||||
@ -3,5 +3,7 @@
|
||||
public class UpdateUserDto
|
||||
{
|
||||
public string? NickName { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
7
backend/IM_API/Dtos/UserDto.cs
Normal file
7
backend/IM_API/Dtos/UserDto.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using IM_API.Models;
|
||||
|
||||
namespace IM_API.Dtos
|
||||
{
|
||||
public record PasswordResetDto(string oldPassword,string Password);
|
||||
public record OnlineStatusSetDto(UserOnlineStatus OnlineStatus);
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using IM_API.Models;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace IM_API.Dtos
|
||||
@ -22,7 +23,7 @@ namespace IM_API.Dtos
|
||||
/// 0(默认):不在线
|
||||
/// 1:在线
|
||||
/// </summary>
|
||||
public sbyte OlineStatus { get; set; }
|
||||
public UserOnlineStatus OnlineStatusEnum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
@ -33,6 +34,6 @@ namespace IM_API.Dtos
|
||||
/// 账户状态
|
||||
/// (0:未激活,1:正常,2:封禁)
|
||||
/// </summary>
|
||||
public sbyte Status { get; set; }
|
||||
public UserStatus StatusEnum { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
using IM_API.Dtos;
|
||||
|
||||
namespace IM_API.Interface.Services
|
||||
{
|
||||
public interface IDemo
|
||||
{
|
||||
TestDto Test();
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,7 @@ namespace IM_API.Interface.Services
|
||||
/// <param name="page">当前页</param>
|
||||
/// <param name="limit">分页大小</param>
|
||||
/// <returns></returns>
|
||||
Task<List<UserInfoDto>> GetFriendListAsync(int userId,int page,int limit);
|
||||
Task<List<FriendInfoDto>> GetFriendListAsync(int userId,int page,int limit,bool desc);
|
||||
/// <summary>
|
||||
/// 新增好友请求
|
||||
/// </summary>
|
||||
@ -27,7 +27,7 @@ namespace IM_API.Interface.Services
|
||||
/// <param name="page"></param>
|
||||
/// <param name="limit"></param>
|
||||
/// <returns></returns>
|
||||
Task<FriendRequest> GetFriendRequestListAsync(int userId,bool isReceived,int page,int limit);
|
||||
Task<FriendRequest> GetFriendRequestListAsync(int userId,bool isReceived,int page,int limit, bool desc);
|
||||
/// <summary>
|
||||
/// 处理好友请求
|
||||
/// </summary>
|
||||
|
||||
@ -22,18 +22,18 @@ namespace IM_API.Interface.Services
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
Task<UserInfoDto> UpdateUserAsync(UpdateUserDto dto);
|
||||
Task<UserInfoDto> UpdateUserAsync(int userId, UpdateUserDto dto);
|
||||
/// <summary>
|
||||
/// 重置用户密码
|
||||
/// </summary>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> ResetPasswordAsync(string password);
|
||||
Task<bool> ResetPasswordAsync(int userId, string oldPassword, string password);
|
||||
/// <summary>
|
||||
/// 更新用户在线状态
|
||||
/// </summary>
|
||||
/// <param name="onlineStatus"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> UpdateOlineStatusAsync(UserOnlineStatus onlineStatus);
|
||||
Task<bool> UpdateOlineStatusAsync(int userId, UserOnlineStatus onlineStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,16 @@ public partial class Friend
|
||||
/// </summary>
|
||||
public DateTime Created { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 好友备注名
|
||||
/// </summary>
|
||||
public string RemarkName { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 好友头像
|
||||
/// </summary>
|
||||
public string? Avatar { get; set; }
|
||||
|
||||
public virtual User FriendNavigation { get; set; } = null!;
|
||||
|
||||
public virtual User User { get; set; } = null!;
|
||||
|
||||
@ -21,6 +21,7 @@ public partial class GroupMember
|
||||
/// 成员角色(0:普通成员,1:管理员,2:群主)
|
||||
/// </summary>
|
||||
public sbyte Role { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加入群聊时间
|
||||
/// </summary>
|
||||
|
||||
99
backend/IM_API/Models/ImContext.Custom.cs
Normal file
99
backend/IM_API/Models/ImContext.Custom.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IM_API.Models
|
||||
{
|
||||
public partial class ImContext
|
||||
{
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Admin>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StateEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<User>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.OnlineStatusEnum);
|
||||
entity.Ignore(e => e.StatusEnum);
|
||||
entity.HasQueryFilter(e => e.IsDeleted == 0);
|
||||
});
|
||||
modelBuilder.Entity<Conversation>(entity =>
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Device>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.DtypeEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<File>(entity =>
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Friend>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StatusEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<FriendRequest>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StateEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Group>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StatusEnum);
|
||||
entity.Ignore(e => e.AllMembersBannedEnum);
|
||||
entity.Ignore(e => e.AuhorityEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<GroupInvite>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StateEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<GroupMember>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.RoleEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<GroupRequest>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StateEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<LoginLog>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StateEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Message>(entity =>
|
||||
{
|
||||
entity.Ignore(e => e.StateEnum);
|
||||
entity.Ignore(e => e.MsgTypeEnum);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Notification>(entity =>
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Permission>(entity =>
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Permissionarole>(entity =>
|
||||
{
|
||||
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Role>(entity =>
|
||||
{
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<Admin>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StateEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -102,7 +101,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<Conversation>(entity =>
|
||||
{
|
||||
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -147,7 +145,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<Device>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.DtypeEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -219,7 +216,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<Friend>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StatusEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -236,12 +232,18 @@ public partial class ImContext : DbContext
|
||||
entity.Property(e => e.Id)
|
||||
.HasColumnType("int(11)")
|
||||
.HasColumnName("ID");
|
||||
entity.Property(e => e.Avatar)
|
||||
.HasMaxLength(255)
|
||||
.HasComment("好友头像");
|
||||
entity.Property(e => e.Created)
|
||||
.HasComment("好友关系创建时间")
|
||||
.HasColumnType("datetime");
|
||||
entity.Property(e => e.FriendId)
|
||||
.HasComment("用户2ID")
|
||||
.HasColumnType("int(11)");
|
||||
entity.Property(e => e.RemarkName)
|
||||
.HasMaxLength(20)
|
||||
.HasComment("好友备注名");
|
||||
entity.Property(e => e.Status)
|
||||
.HasComment("当前好友关系状态\r\n(0:待通过,1:已添加,2:已拒绝,3:已拉黑)")
|
||||
.HasColumnType("tinyint(4)");
|
||||
@ -262,7 +264,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<FriendRequest>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StateEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -306,9 +307,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<Group>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StatusEnum);
|
||||
entity.Ignore(x => x.AllMembersBannedEnum);
|
||||
entity.Ignore(x => x.AuhorityEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -353,7 +351,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<GroupInvite>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StateEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -402,7 +399,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<GroupMember>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.RoleEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -446,7 +442,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<GroupRequest>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StateEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -488,7 +483,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<LoginLog>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StateEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -523,8 +517,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<Message>(entity =>
|
||||
{
|
||||
entity.Ignore(x => x.StateEnum);
|
||||
entity.Ignore(x => x.MsgTypeEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -689,10 +681,6 @@ public partial class ImContext : DbContext
|
||||
|
||||
modelBuilder.Entity<User>(entity =>
|
||||
{
|
||||
|
||||
// 忽略包装枚举属性
|
||||
entity.Ignore(e => e.OnlineStatusEnum);
|
||||
entity.Ignore(e => e.StatusEnum);
|
||||
entity.HasKey(e => e.Id).HasName("PRIMARY");
|
||||
|
||||
entity
|
||||
@ -707,6 +695,9 @@ public partial class ImContext : DbContext
|
||||
entity.Property(e => e.Id)
|
||||
.HasColumnType("int(11)")
|
||||
.HasColumnName("ID");
|
||||
entity.Property(e => e.Avatar)
|
||||
.HasMaxLength(255)
|
||||
.HasComment("用户头像链接");
|
||||
entity.Property(e => e.Created)
|
||||
.HasDefaultValueSql("'1970-01-01 00:00:00'")
|
||||
.HasComment("创建时间")
|
||||
|
||||
@ -52,6 +52,11 @@ public partial class User
|
||||
/// </summary>
|
||||
public sbyte IsDeleted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户头像链接
|
||||
/// </summary>
|
||||
public string? Avatar { get; set; }
|
||||
|
||||
public virtual ICollection<Conversation> Conversations { get; set; } = new List<Conversation>();
|
||||
|
||||
public virtual ICollection<Device> Devices { get; set; } = new List<Device>();
|
||||
|
||||
@ -87,6 +87,15 @@ namespace IM_API
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
|
||||
options.Events = new JwtBearerEvents
|
||||
{
|
||||
OnAuthenticationFailed = context =>
|
||||
{
|
||||
Console.WriteLine("Authentication failed: " + context.Exception.Message);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
});
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
@ -104,8 +113,9 @@ namespace IM_API
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthorization();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
@ -35,20 +35,10 @@ namespace IM_API.Services
|
||||
public async Task<UserInfoDto> RegisterAsync(RegisterRequestDto dto)
|
||||
{
|
||||
string username = dto.Username;
|
||||
string password = dto.Password;
|
||||
string nickname = dto.NickName;
|
||||
//用户是否存在
|
||||
bool isExist = await _context.Users.AnyAsync(x => x.Username == username);
|
||||
if (isExist) throw new BaseException(CodeDefine.USER_ALREADY_EXISTS);
|
||||
User user = new User
|
||||
{
|
||||
Username = username,
|
||||
Password = password,
|
||||
NickName = nickname,
|
||||
OnlineStatusEnum = UserOnlineStatus.Offline,
|
||||
StatusEnum = UserStatus.Normal,
|
||||
Created = DateTime.Now
|
||||
};
|
||||
User user = _mapper.Map<User>(dto);
|
||||
_context.Users.Add(user);
|
||||
await _context.SaveChangesAsync();
|
||||
return _mapper.Map<UserInfoDto>(user);
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Interface.Services;
|
||||
|
||||
namespace IM_API.Services
|
||||
{
|
||||
public class Demo : IDemo
|
||||
{
|
||||
public TestDto Test()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,67 @@
|
||||
using IM_API.Models;
|
||||
using AutoMapper;
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Interface.Services;
|
||||
using IM_API.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IM_API.Services
|
||||
{
|
||||
public class FriendService
|
||||
public class FriendService : IFriendSerivce
|
||||
{
|
||||
|
||||
private readonly ImContext _context;
|
||||
private readonly ILogger<FriendService> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
public FriendService(ImContext context, ILogger<FriendService> logger, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public Task<bool> BlockeFriendAsync(int friendId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> BlockFriendByUserIdAsync(int userId, int toUserId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> DeleteFriendAsync(int friendId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> DeleteFriendByUserIdAsync(int userId, int toUserId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<List<FriendInfoDto>> GetFriendListAsync(int userId, int page, int limit, bool desc)
|
||||
{
|
||||
var query = _context.Friends.Where(x => x.UserId == userId);
|
||||
if (desc)
|
||||
{
|
||||
query = query.OrderByDescending(x => x.UserId);
|
||||
}
|
||||
var friendList = await query.Skip((page - 1 * limit)).Take(limit).ToListAsync();
|
||||
return _mapper.Map<List<FriendInfoDto>>(friendList);
|
||||
}
|
||||
|
||||
public Task<FriendRequest> GetFriendRequestListAsync(int userId, bool isReceived, int page, int limit, bool desc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> HandleFriendRequestAsync(HandleFriendRequestDto requestDto)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> SendFriendRequestAsync(FriendRequestDto friendRequest)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
77
backend/IM_API/Services/UserService.cs
Normal file
77
backend/IM_API/Services/UserService.cs
Normal file
@ -0,0 +1,77 @@
|
||||
using AutoMapper;
|
||||
using IM_API.Dtos;
|
||||
using IM_API.Exceptions;
|
||||
using IM_API.Interface.Services;
|
||||
using IM_API.Models;
|
||||
using IM_API.Tools;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IM_API.Services
|
||||
{
|
||||
public class UserService : IUserService
|
||||
{
|
||||
private readonly ImContext _context;
|
||||
private readonly ILogger<UserService> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
public UserService(ImContext imContext,ILogger<UserService> logger,IMapper mapper)
|
||||
{
|
||||
this._context = imContext;
|
||||
this._logger = logger;
|
||||
this._mapper = mapper;
|
||||
}
|
||||
#region 获取用户信息
|
||||
public async Task<UserInfoDto> GetUserInfoAsync(int userId)
|
||||
{
|
||||
var user = await _context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
if (user == null)
|
||||
{
|
||||
throw new BaseException(CodeDefine.USER_NOT_FOUND);
|
||||
}
|
||||
return _mapper.Map<UserInfoDto>(user);
|
||||
}
|
||||
#endregion
|
||||
#region 通过用户名获取用户信息
|
||||
public async Task<UserInfoDto> GetUserInfoByUsernameAsync(string username)
|
||||
{
|
||||
var user = await _context.Users.FirstOrDefaultAsync(x => x.Username == username);
|
||||
if (user == null)
|
||||
{
|
||||
throw new BaseException(CodeDefine.USER_NOT_FOUND);
|
||||
}
|
||||
return _mapper.Map<UserInfoDto>(user);
|
||||
}
|
||||
#endregion
|
||||
#region 重置用户密码
|
||||
public async Task<bool> ResetPasswordAsync(int userId, string oldPassword, string password)
|
||||
{
|
||||
var user = await _context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
if (user is null) throw new BaseException(CodeDefine.USER_NOT_FOUND);
|
||||
//验证原密码
|
||||
if (user.Password != oldPassword) throw new BaseException(CodeDefine.PASSWORD_ERROR);
|
||||
user.Password = password;
|
||||
await _context.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
#region 更新用户在线状态
|
||||
public async Task<bool> UpdateOlineStatusAsync(int userId,UserOnlineStatus onlineStatus)
|
||||
{
|
||||
var user = await _context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
if (user is null) throw new BaseException(CodeDefine.USER_NOT_FOUND);
|
||||
user.OnlineStatusEnum = onlineStatus;
|
||||
await _context.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
#region 更新用户信息
|
||||
public async Task<UserInfoDto> UpdateUserAsync(int userId,UpdateUserDto dto)
|
||||
{
|
||||
var user = await _context.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
if (user is null) throw new BaseException(CodeDefine.USER_NOT_FOUND);
|
||||
_mapper.Map(dto,user);
|
||||
await _context.SaveChangesAsync();
|
||||
return _mapper.Map<UserInfoDto>(user);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Jwt": {
|
||||
"Key": "change_this_super_secret_key_in_prod",
|
||||
"Key": "YourSuperSecretKey123456784124214190!",
|
||||
"Issuer": "IMDemo",
|
||||
"Audience": "IMClients",
|
||||
"AccessTokenMinutes": 15,
|
||||
|
||||
39
docs/数据字典.md
39
docs/数据字典.md
@ -4,29 +4,32 @@
|
||||
|
||||
#### 表说明:储存用户个人信息
|
||||
|
||||
| 字段名 | 数据类型 | 是否必填 | 默认值 | 主/外键 | 约束/索引 | 字段说明 | 示例值 |
|
||||
| ----------- | ----------- | -------- | -------- | ------- | --------- | ------------------------------------------------ | --------- |
|
||||
| Id | INT | 是 | / | 主键 | 索引 | 主键自增 | 1 |
|
||||
| Username | VARCHAR(50) | 是 | / | / | 唯一 | 唯一用户名 | admin |
|
||||
| Password | VARCHAR(50) | 是 | / | / | / | 用户密码 | 123456 |
|
||||
| NickName | VARCHAR(50) | 是 | / | / | / | 用户昵称 | / |
|
||||
| OlineStatus | TINYINT | 是 | 0 | / | / | 用户在线状态<br />0(默认):不在线<br />1:在线 | 0 |
|
||||
| Created | DATETIME | 是 | 1970/1/1 | / | / | 账户创建时间 | 2025/9/29 |
|
||||
| Updated | DATETIME | 否 | / | / | / | 账户修改时间 | 2024/9/29 |
|
||||
| Status | TINYINT | 是 | 1 | / | / | 账户状态<br />(0:未激活,1:正常,2:封禁) | 1 |
|
||||
| IsDeleted | TINYINT | 是 | 0 | / | / | 软删除标识<br />0:账号正常<br />1:账号已删除 | 0 |
|
||||
| 字段名 | 数据类型 | 是否必填 | 默认值 | 主/外键 | 约束/索引 | 字段说明 | 示例值 |
|
||||
| ----------- | ------------ | -------- | -------- | ------- | --------- | ------------------------------------------------ | ----------------------- |
|
||||
| Id | INT | 是 | / | 主键 | 索引 | 主键自增 | 1 |
|
||||
| Username | VARCHAR(50) | 是 | / | / | 唯一 | 唯一用户名 | admin |
|
||||
| Avatar | VARCHAR(255) | 否 | / | / | / | 用户头像 | https://baidu.com/1.png |
|
||||
| Password | VARCHAR(50) | 是 | / | / | / | 用户密码 | 123456 |
|
||||
| NickName | VARCHAR(50) | 是 | / | / | / | 用户昵称 | / |
|
||||
| OlineStatus | TINYINT | 是 | 0 | / | / | 用户在线状态<br />0(默认):不在线<br />1:在线 | 0 |
|
||||
| Created | DATETIME | 是 | 1970/1/1 | / | / | 账户创建时间 | 2025/9/29 |
|
||||
| Updated | DATETIME | 否 | / | / | / | 账户修改时间 | 2024/9/29 |
|
||||
| Status | TINYINT | 是 | 1 | / | / | 账户状态<br />(0:未激活,1:正常,2:封禁) | 1 |
|
||||
| IsDeleted | TINYINT | 是 | 0 | / | / | 软删除标识<br />0:账号正常<br />1:账号已删除 | 0 |
|
||||
|
||||
### 表名:Friends
|
||||
|
||||
#### 表说明:好友关系映射
|
||||
|
||||
| 字段名 | 数据类型 | 是否必填 | 默认值 | 主/外键 | 约束/索引 | 字段说明 | 示例值 |
|
||||
| -------- | -------- | -------- | -------- | ---------------- | --------- | ------------------------------------------------------------ | --------- |
|
||||
| Id | INT | 是 | / | 主键 | 索引 | 主键自增 | 1 |
|
||||
| UserId | INT | 是 | / | 外键(Users.Id) | 索引 | 用户ID | 1 |
|
||||
| FriendId | INT | 是 | / | 外键(Users.Id) | 索引 | 用户2ID | 2 |
|
||||
| Status | TINYINT | 是 | 0 | / | / | 当前好友关系状态<br />(0:待通过,1:已添加,2:已拒绝,3:已拉黑) | 0 |
|
||||
| Created | DATETIME | 是 | 1970/1/1 | / | / | 好友关系创建时间 | 2025/9/29 |
|
||||
| 字段名 | 数据类型 | 是否必填 | 默认值 | 主/外键 | 约束/索引 | 字段说明 | 示例值 |
|
||||
| ---------- | ------------ | -------- | -------- | ---------------- | --------- | ------------------------------------------------------------ | ----------------------- |
|
||||
| Id | INT | 是 | / | 主键 | 索引 | 主键自增 | 1 |
|
||||
| UserId | INT | 是 | / | 外键(Users.Id) | 索引 | 用户ID | 1 |
|
||||
| FriendId | INT | 是 | / | 外键(Users.Id) | 索引 | 用户2ID | 2 |
|
||||
| RemarkName | VARCHAR(20) | 是 | / | / | / | 好友备注 | 小王 |
|
||||
| Avatar | VARCHAR(255) | 否 | / | / | / | 好友头像 | https://baidu.com/1.png |
|
||||
| Status | TINYINT | 是 | 0 | / | / | 当前好友关系状态<br />(0:待通过,1:已添加,2:已拒绝,3:已拉黑) | 0 |
|
||||
| Created | DATETIME | 是 | 1970/1/1 | / | / | 好友关系创建时间 | 2025/9/29 |
|
||||
|
||||
### 表名:Groups
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user