FalconSSO/FAuth/Controllers/api/UserController.cs

263 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using Falcon.Extend;
using FAuth.DataBase.Tables;
using FAuth.Extensions;
using FAuth.Extensions.Account;
using FAuth.Extensions.Decryptor;
using FAuth.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace FAuth.Controllers.api
{
/// <summary>
/// 用户相关api控制器接口
/// </summary>
public class UserController:ApiControllerBase<UserController>
{
public IUserTicketDryptor UserTicketDryptor { get; set; }
public AccountHelper Account { get; set; }
public UserController(ILogger<UserController> logger,IServiceProvider service)
: base(logger,service) {
this.Account = service.GetRequiredService<AccountHelper>();
this.UserTicketDryptor = service.GetRequiredService<IUserTicketDryptor>();
}
/// <summary>
/// 用户登录方法
/// </summary>
/// <param name="userName">用户名</param>
/// <param name="password">密码</param>
/// <returns>登录结果</returns>
[HttpPost]
[ProducesResponseType(typeof(CheckUserResult),200)]
public CheckUserResult Login(string userName,string password) {
if(userName.IsNullOrEmpty()) {
throw new ApiArgumentNullException(nameof(userName));
}
var qu = this.Db.Users.Where(m => m.UserName == userName && m.Password == password);
if(!qu.Any()) {
throw new ApiException("提供的用户名或密码不正确");
}
var fir = qu.First();
var now = DateTimeOffset.Now;
fir.LastLoginDatetime = now;
fir.Status |= FUserStatusEnum.Login;
this.Db.SaveChangesAsync().Wait();
this.Logger.LogInformation($"用户{userName}登录成功!");
return new CheckUserResult {
Ticket = this.UserTicketDryptor.Encrypt(new UserTicketModel {
Id = fir.Id,
UserName = fir.UserName,
LoginDatetime = now,
}),
};
}
/// <summary>
/// 登出用户
/// </summary>
/// <param name="ticket">用户票据</param>
/// <returns>是否成功</returns>
[HttpPost]
public bool Logout(string ticket) {
if(ticket.IsNullOrEmpty()) {
throw new ApiArgumentNullException(nameof(ticket));
}
var userTicketModel = this.UserTicketDryptor.Decrypt(ticket);
var qu = this.Db.Users.Where(m => m.Id == userTicketModel.Id);
if(!qu.Any()) {
throw new ApiException("提交的票据信息错误");
}
var fir = qu.First();
fir.Status &= ~FUserStatusEnum.Login;
fir.LastLogoutDatetime = DateTimeOffset.Now;
this.Db.SaveChangesAsync().Wait();
this.Logger.LogInformation($"用户{userTicketModel.Id}:{userTicketModel.UserName}登出成功!");
return true;
}
/// <summary>
/// 根据用户凭据获取用户信息
/// </summary>
/// <param name="ticket">登录票据</param>
/// <returns>用户信息</returns>
[HttpGet]
[ProducesResponseType(typeof(UserInfo),200)]
public UserInfo GetUserByTicket(string ticket) {
if(ticket.IsNullOrEmpty()) {
throw new ApiArgumentNullException(nameof(ticket));
}
var userTicketModel = this.UserTicketDryptor.Decrypt(ticket);
var qu = this.Db.Users.Where(m => m.Id == userTicketModel.Id);
if(!qu.Any()) {
throw new ApiException("提交的票据信息错误");
}
var fir = qu.First();
if(fir.LastLogoutDatetime.HasValue && userTicketModel.LoginDatetime < fir.LastLogoutDatetime.Value) {
throw new ApiException("用户已登出");
}
return new UserInfo {
Id = fir.Id,
LastLoginDatetime = fir.LastLoginDatetime,
UserName = fir.UserName,
Name = fir.Name,
};
}
/// <summary>
/// 获取用户信息列表
/// </summary>
/// <param name="userName">登录用户名</param>
/// <param name="name">用户名</param>
/// <returns>用户信息列表</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<UserInfo>),200)]
public IEnumerable<UserInfo> GetUsers(string userName,string name) {
var key = $"FAuth:Users:userName:{userName}:name:{name}";
List<UserInfo> result = null;// this.Cache?.GetObj<List<UserInfo>>(key);
if(result == null) {
var qu = this.Db.Users
.Select(m => new UserInfo {
Id = m.Id,
UserName = m.UserName,
Name = m.Name,
LastLoginDatetime = m.LastLoginDatetime,
Status =
!m.LastLoginDatetime.HasValue ? "未登陆" :
!m.LastLogoutDatetime.HasValue ? "在线" :
m.LastLoginDatetime.Value > m.LastLogoutDatetime.Value ? "在线" : "离线",
});
if(userName.IsNotNullOrEmpty()) {
qu = qu.Where(m => m.UserName == userName);
}
if(name.IsNotNullOrEmpty()) {
qu = qu.Where(m => m.Name == name);
}
result = qu.ToList();
this.Cache?.SetCache(key,result,new TimeSpan(0,5,0));
}
return result;
}
/// <summary>
/// 根据提供的登陆票据修改用户密码
/// </summary>
/// <param name="ticket">票据</param>
/// <param name="nPassword">新密码</param>
/// <returns>是否成功</returns>
[HttpPost]
public bool ChangePassword(string ticket,string nPassword) {
if(ticket.IsNullOrEmpty()) {
throw new ApiArgumentNullException(nameof(ticket));
}
var userTicketModel = this.UserTicketDryptor.Decrypt(ticket);
var qu = this.Db.Users.Where(m => m.Id == userTicketModel.Id);
if(!qu.Any()) {
throw new ApiException("没找到票据对应用户");
}
foreach(var item in qu) {
item.Password = nPassword;
}
this.Db.SaveChangesAsync().Wait();
this.Logger.LogInformation($"用户{userTicketModel.Id}:{userTicketModel.UserName}修改密码成功!");
return true;
}
/// <summary>
/// 通过提供管理员票据和新用户信息创建用户
/// </summary>
/// <param name="adminTicket">管理员票据</param>
/// <param name="userName">登录用户名</param>
/// <param name="name">用户名称</param>
/// <param name="password">用户密码</param>
/// <returns>是否成功</returns>
[HttpPost]
[ProducesResponseType(typeof(UserInfo),200)]
public UserInfo AddNewUser(string adminTicket,string userName,string name,string password) {
if(adminTicket is null)
throw new ApiArgumentNullException(nameof(adminTicket));
if(userName is null)
throw new ApiArgumentNullException(nameof(userName));
if(password is null)
throw new ApiArgumentNullException(nameof(password));
if(this.Account.IsNotSystemAdmin(adminTicket)) {
throw new ApiException($"用户必须在应用FAuth中具有Admin角色");
}
var qu = this.Db.Users.Where(m => m.UserName == userName);
if(qu.Any()) {
throw new ApiException("用户登录名已经存在,不能重复添加");
}
var nUser = new FUser {
Name = name,
UserName = userName,
Password = password,
};
this.Db.Entry(nUser).State = EntityState.Added;
this.Db.SaveChangesAsync().Wait();
this.Logger.LogInformation($"用户{nUser.Id}:{nUser.UserName}:{nUser.Name}添加成功!");
return new UserInfo {
Id = nUser.Id,
UserName = nUser.UserName,
Name = nUser.Name,
LastLoginDatetime = nUser.LastLoginDatetime,
};
}
/// <summary>
/// 重置用户密码
/// </summary>
/// <param name="adminTicket">管理员票据</param>
/// <param name="userName">要重置密码的用户名</param>
/// <param name="newPassword">新密码</param>
/// <returns>是否成功。成功True 否则返回False</returns>
[HttpPost]
public bool ResetUserPassword(string adminTicket,string userName,string newPassword) {
if(adminTicket is null)
throw new ApiArgumentNullException(nameof(adminTicket));
if(userName is null)
throw new ApiArgumentNullException(nameof(userName));
if(newPassword is null)
throw new ApiArgumentNullException(nameof(newPassword));
if(this.Account.IsNotSystemAdmin(adminTicket)) {
throw new ApiException($"用户必须在应用FAuth中具有Admin角色");
}
var qu = this.Db.Users.Where(m => m.UserName == userName);
if(!qu.Any()) {
throw new ApiException("用户登录名不存在");
}
foreach(var item in qu) {
item.Password = newPassword;
}
this.Db.SaveChangesAsync().Wait();
return true;
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="adminTicket">管理员凭据</param>
/// <param name="id">要删除的用户编号</param>
/// <returns>删除结果</returns>
[HttpPost, ProducesResponseType(typeof(ApiBoolResult),200)]
public ApiBoolResult RemoveUser(string adminTicket,int id) {
var user = this.Account.TicketDryptor.Decrypt(adminTicket);
if(user.Id == id) {
throw new ApiException("当前用户不能删除");
}
this.Db.Users.Attach(new FUser {
Id = id,
}).State = EntityState.Deleted;
this.Db.SaveChangesAsync().Wait();
return new ApiBoolResult { Result = true };
}
}
}