123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- using Hotline.Application.Contracts.Configurations;
- using Hotline.Caches;
- using Hotline.CallCenter.Tels;
- using Hotline.Permissions;
- using Hotline.Share.Dtos.CallCenter;
- using Hotline.Share.Dtos.User;
- using Hotline.Users;
- using Identity.Admin.HttpClient;
- using Identity.Shared.Dtos;
- using Identity.Shared.Dtos.Account;
- using Identity.Shared.Dtos.Identity;
- using Identity.Shared.Dtos.Role;
- using MapsterMapper;
- using Microsoft.AspNetCore.Mvc;
- using XF.Domain.Authentications;
- using XF.Domain.Exceptions;
- using Microsoft.Extensions.Options;
- using XF.Utility.AppIdentityModel;
- using XF.Utility.UnifyResponse;
- namespace Hotline.Api.Controllers;
- /// <summary>
- /// 用户管理相关接口
- /// </summary>
- public class UserController : BaseController
- {
- private readonly ISessionContext _sessionContext;
- private readonly IUserDomainService _userDomainService;
- private readonly ITelRepository _telRepository;
- private readonly IUserRepository _userRepository;
- private readonly ITelCacheManager _telCacheManager;
- private readonly IUserCacheManager _userCacheManager;
- private readonly IIdentityClient _identityClient;
- private readonly IOptionsSnapshot<IdentityConfigs> _identityConfigs;
- private readonly IMapper _mapper;
- public UserController(
- ISessionContext sessionContext,
- IUserDomainService userDomainService,
- ITelRepository telRepository,
- IUserRepository userRepository,
- ITelCacheManager telCacheManager,
- IUserCacheManager userCacheManager,
- IIdentityClient identityClient,
- IOptionsSnapshot<IdentityConfigs> identityConfigs,
- IMapper mapper)
- {
- _sessionContext = sessionContext;
- _userDomainService = userDomainService;
- _telRepository = telRepository;
- _userRepository = userRepository;
- _telCacheManager = telCacheManager;
- _userCacheManager = userCacheManager;
- _identityClient = identityClient;
- _identityConfigs = identityConfigs;
- _mapper = mapper;
- }
- /// <summary>
- /// 上班
- /// </summary>
- [Permission(EPermission.OnDuty)]
- [HttpPost("on-duty/{telNo}")]
- public async Task OnDuty([FromRoute] string? telNo)
- {
- if (string.IsNullOrEmpty(telNo))
- {
- var user = await _userRepository.GetAsync(d => !d.IsDeleted && d.Id == _sessionContext.RequiredUserId,
- HttpContext.RequestAborted);
- if (user == null)
- throw UserFriendlyException.SameMessage("无效用户编号");
- if (string.IsNullOrEmpty(user.DefaultTelNo))
- throw UserFriendlyException.SameMessage("未设置默认分机号");
- telNo = user.DefaultTelNo;
- }
- var tel = _telCacheManager.GetTel(telNo);
- await _userDomainService.OnDutyAsync(_sessionContext.RequiredUserId, tel, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 下班
- /// </summary>
- [Permission(EPermission.OffDuty)]
- [HttpPost("off-duty")]
- public Task<WorkDto?> OffDuty()
- {
- return _userDomainService.OffDutyAsync(_sessionContext.RequiredUserId, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 分页查询用户
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.QueryPagedUser)]
- [HttpGet("paged")]
- public async Task<PagedDto<UserDto>> QueryPaged([FromQuery] UserPagedDto dto)
- {
- var (total, items) = await _userRepository.QueryPagedAsync(
- d => !d.IsDeleted,
- d => d.OrderByDescending(x => x.CreationTime),
- dto.PageIndex,
- dto.PageSize,
- (!string.IsNullOrEmpty(dto.PhoneNo), d => d.PhoneNo.Contains(dto.PhoneNo!)),
- (!string.IsNullOrEmpty(dto.DisplayName), d => !string.IsNullOrEmpty(d.Name) && d.Name.Contains(dto.DisplayName!)));
- return new PagedDto<UserDto>(total, _mapper.Map<IReadOnlyList<UserDto>>(items));
- }
- /// <summary>
- /// 更新用户
- /// </summary>
- /// <param name="userDto"></param>
- /// <returns></returns>
- [Permission(EPermission.UpdateUser)]
- [HttpPut]
- public async Task Update([FromBody] UpdateUserDto userDto)
- {
- var user = await _userRepository.GetAsync(userDto.Id, HttpContext.RequestAborted);
- if (user is null || user.IsDeleted)
- throw UserFriendlyException.SameMessage("无效用户编号");
- if (await IsAccountLock(user.Id))
- throw UserFriendlyException.SameMessage("该账号已被锁定");
- _mapper.Map(userDto, user);
- await _userRepository.UpdateAsync(user, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 新增用户
- /// </summary>
- /// <param name="userDto"></param>
- /// <returns></returns>
- [Permission(EPermission.AddUser)]
- [HttpPost]
- public async Task<string> Add([FromBody] AddUserDto userDto)
- {
- var getAccountRsp = await _identityClient.GetUserAsync(userDto.UserName, HttpContext.RequestAborted);
- CheckHttpRequestSuccess(getAccountRsp, "GetUserAsync");
- var account = getAccountRsp.Result;
- if (account is null)
- {
- var identityConfigs = _identityConfigs.Value;
- var addAccountRsp = await _identityClient.AddUserAsync(new IdentityUserDto
- {
- ClientId = identityConfigs.ClientId,
- UserName = userDto.UserName,
- Email = $"{userDto.UserName}@fw.com",
- DislayName = userDto.Name ?? userDto.UserName
- }, HttpContext.RequestAborted);
- if (addAccountRsp is null || !addAccountRsp.IsSuccess)
- throw new UserFriendlyException("identity service insert fail: AddUserAsync", "新增用户失败!");
- var user = _mapper.Map<User>(userDto);
- user.Id = addAccountRsp.Result;
- return await _userRepository.AddAsync(user, HttpContext.RequestAborted);
- }
- else
- {
- if (await IsAccountLock(account.Id))
- throw UserFriendlyException.SameMessage("该账号已被锁定,请联系管理员");
- var user = await _userRepository.GetAsync(account.Id, HttpContext.RequestAborted);
- if (user is null)
- {
- user = _mapper.Map<User>(userDto);
- user.Id = account.Id;
- return await _userRepository.AddAsync(user, HttpContext.RequestAborted);
- }
- if (user.IsDeleted)
- {
- user.Recover();
- await _userRepository.UpdateAsync(user);
- return user.Id;
- }
- throw UserFriendlyException.SameMessage("该用户已存在");
- }
- }
- /// <summary>
- /// 删除用户
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- [Permission(EPermission.RemoveUser)]
- [HttpDelete("{id}")]
- public async Task Remove(string id)
- {
- var work = _userCacheManager.GetWorkByUser(id);
- if (work is not null)
- throw UserFriendlyException.SameMessage("该用户正在工作中,请下班以后再删除");
- var response = await _identityClient.LockUserAsync(new UserLockDto(id), HttpContext.RequestAborted);
- CheckHttpRequestSuccess(response, "LockUserAsync");
- await _userRepository.RemoveAsync(id, true, HttpContext.RequestAborted);
- }
- /// <summary>
- /// 查询用户当前状态
- /// </summary>
- /// <returns></returns>
- //[AllowAnonymous]
- [HttpGet("state")]
- public async Task<UserStateDto> GetUserState()
- {
- var userId = _sessionContext.RequiredUserId;
- var isOnDuty = await _userCacheManager.IsWorkingByUserAsync(userId, HttpContext.RequestAborted);
- var isResting = false;
- var telNo = string.Empty;
- if (isOnDuty)
- {
- var work = _userCacheManager.GetWorkByUser(userId);
- isResting = await _telRepository.IsRestingAsync(work.TelNo, HttpContext.RequestAborted);
- telNo = work.TelNo;
- }
- return new UserStateDto(isOnDuty, isResting, telNo);
- }
- /// <summary>
- /// 分页查询用户角色
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.GetUserRoles)]
- [HttpGet("roles")]
- public async Task<PagedDto<IdentityRoleDto>> GetUserRoles([FromQuery] UserRolesPagedDto dto)
- {
- var pageDto = _mapper.Map<PageDto>(dto);
- var getUserRolesRsp = await _identityClient.GetUserRolesAsync(dto.UserId, pageDto, HttpContext.RequestAborted);
- CheckHttpRequestSuccess(getUserRolesRsp, "GetUserRolesAsync");
- var result = getUserRolesRsp.Result;
- return new PagedDto<IdentityRoleDto>(result.TotalCount, result.Roles);
- }
- /// <summary>
- /// 设置用户角色
- /// </summary>
- /// <returns></returns>
- [Permission(EPermission.SetUserRoles)]
- [HttpPost("roles")]
- public async Task SetUserRoles([FromBody] SetUserRolesDto dto)
- {
- var setUserRolesRsp = await _identityClient.SetUserRolesAsync(dto, HttpContext.RequestAborted);
- CheckHttpRequestSuccess(setUserRolesRsp, "SetUserRolesAsync");
- }
- /// <summary>
- /// 查询密码更改状态
- /// </summary>
- /// <returns></returns>
- /// <exception cref="UserFriendlyException"></exception>
- [Permission(EPermission.GetPasswordChangeStatus)]
- [HttpGet("pwd-changed")]
- public Task<bool> GetPasswordChangeStatus()
- {
- var claim = User.Claims.FirstOrDefault(d => d.Type == AppClaimTypes.UserPasswordChanged);
- if (claim is null)
- throw UserFriendlyException.SameMessage("无密码更改信息");
- return Task.FromResult(Convert.ToBoolean(claim.Value));
- }
- /// <summary>
- /// 修改密码
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpPost("change-pwd")]
- public async Task ChangePassword([FromBody] ChangePasswordDto dto)
- {
- var changepwdDto = _mapper.Map<UserChangePasswordDto>(dto);
- changepwdDto.UserId = _sessionContext.RequiredUserId;
- var changepwdRsp = await _identityClient.ChangePasswordAsync(changepwdDto, HttpContext.RequestAborted);
- CheckHttpRequestSuccess(changepwdRsp, "ChangePasswordAsync");
- }
- /// <summary>
- /// 重置密码
- /// </summary>
- /// <returns></returns>
- [HttpPost("initial-pwd/{userId}")]
- public async Task InitialPassword(string userId)
- {
- var initpwdRsp = await _identityClient.InitialPasswordAsync(userId, HttpContext.RequestAborted);
- CheckHttpRequestSuccess(initpwdRsp, "InitialPasswordAsync");
- }
- #region private
- private async Task<bool> IsAccountLock(string userId)
- {
- var response = await _identityClient.IsAccountLockAsync(userId, HttpContext.RequestAborted);
- if (response is null || !response.IsSuccess)
- throw new UserFriendlyException("identity service request fail: IsAccountLockAsync");
- return response.Result;
- }
- private void CheckHttpRequestSuccess(ApiResponse response, string msg)
- {
- if (response == null || !response.IsSuccess)
- throw new UserFriendlyException($"identity service request failed: {msg}");
- }
- #endregion
- }
|