Files
SystemX.Web/Projects/WebApi/AuthApi/Services/AuthService.cs

274 lines
12 KiB
C#

using SystemX.Core.Model.Auth;
using SystemX.Core.Services;
using SystemX.Core;
using WebApi.Library.Config;
using SystemX.Core.Config.Model;
using System.Data;
using SystemX.Core.DB;
using Microsoft.EntityFrameworkCore;
using WebApi.Library.DBContext.DB.DBContext.AccountDB.Context;
using WebApi.Library.DBContext.DB.DBContext.AccountDB.Tables;
namespace AuthApi.Services
{
public class AuthService
{
private readonly IServiceProvider _serviceProvider;
private readonly IServiceScopeFactory _scopeFactory;
private readonly ConfigService<WebApiConfig>? _configService;
private static List<LoginResponse> Session = new List<LoginResponse>();
public AuthService(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, ConfigService<WebApiConfig> configSerice)
{
_serviceProvider = serviceProvider;
_configService = configSerice;
_scopeFactory = scopeFactory;
}
/// <summary>
/// create new user
/// </summary>
public async Task<RegisterResponse> CreateUser(Register registerModel)
{
RegisterResponse response = new RegisterResponse();
response.EC = ERROR_CODE.EC_USER_REGISTER_FAILED;
response.UserID = registerModel.UserID;
response.Role = registerModel.Role;
response.RoleName = registerModel.Role.ToString();
//context
using (var scope = _scopeFactory.CreateScope())
{
var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
using (var context = GetAccountDBContext(provider, 1))
{
if (context is not null)
{
var user = await context.TUsers.AsNoTracking().Where(x => x.CUserId.ToLower() == registerModel.UserID.ToLower()).ToListAsync();
if (user?.Count <= 0)
{
string auid = Guid.NewGuid().ToString();
//user
TUser newUser = new TUser
{
CAuid = auid,
CUserId = registerModel.UserID,
CPasswordHashed = registerModel.Password,
CCreateDateTime = DateTime.Now,
CLastLoginDateTime = new DateTime()
};
//role
TRole newUserRole = new TRole
{
CAuid = auid,
CRoleId = Convert.ToByte(registerModel.Role),
CRoleName = registerModel.Role.ToString()
};
using (var transaction = await context.CreateTransactionAsync())
{
await context.AddAsync(newUser);
await context.AddAsync(newUserRole);
var result = await context.CloseTransactionAsync(transaction);
if (result == true)
{
response.EC = ERROR_CODE.EC_OK;
}
}
}
}
}
}
return response;
}
/// <summary>
/// select user(login)
/// </summary>
public async Task<LoginResponse> SelectUser(Login loginModel)
{
//response
LoginResponse response = new LoginResponse();
response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED;
response.UserID = loginModel.UserID;
var session = Session.Find(x => x.UserID?.ToLower() == loginModel.UserID?.ToLower());
if (session?.AccessTokenExpired < DateTime.Now.ToUnixTime())
{
Session.Remove(session);
}
//기존 로그인 체크
if (Session.Exists(x => x.UserID == $"{loginModel.UserID?.ToLower()}") == false)
{
if (loginModel != null)
{
//context
using (var scope = _scopeFactory.CreateScope())
{
var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
using (var context = GetAccountDBContext(provider, 1))
{
if (context is not null)
{
try
{
using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted))
{
//select user
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
{
if (selectUser.CPasswordHashed == loginModel?.Password)
{
//select role
var selectRole = await context.TRoles.FindAsync(selectUser.CAuid);
if (selectRole != null)
{
response.Role = (UserRole)Enum.Parse(typeof(UserRole), selectRole.CRoleId.ToString());
response.RoleName = selectRole.CRoleName;
}
Session.Add(response);
if (selectUser.CState == (byte)UserState.Active)
{
response.EC = ERROR_CODE.EC_OK;
}
else if (selectUser.CState == (byte)UserState.Inactive)
{
response.EC = ERROR_CODE.EC_USER_LOGIN_INAVTIVE;
}
else if (selectUser.CState == (byte)UserState.Block)
{
response.EC = ERROR_CODE.EC_USER_LOGIN_BLOCKED;
}
}
else
{
response.EC = ERROR_CODE.EC_USER_LOGIN_INVALID_PASSWORD;
}
}
else
{
response.EC = ERROR_CODE.EC_USER_LOGIN_NOT_EXIST;
Log4net.WriteLine($"{response.EC}", LogType.Error);
}
await context.CloseTransactionAsync(transaction);
}
}
catch (Exception e)
{
Log4net.WriteLine($"Select User Transaction Error", LogType.Exception);
Log4net.WriteLine(e);
}
}
}
}
}
}
return response;
}
public async Task<bool> UpdateLoginInfo(Login loginModel, string? RefreshToken = "")
{
bool result = false;
bool transactionResult = true;
using (var scope = _scopeFactory.CreateScope())
{
var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
using (var context = GetAccountDBContext(provider, 1))
{
if (context is not null)
{
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
{
using (var transaction = await context.CreateTransactionAsync())
{
try
{
//user info
selectUser.CLastLoginDateTime = DateTime.Now;
context.Update(selectUser);
//refresh token
var findRefreshToken = await context.TRefreshTokens.AsNoTracking().FirstOrDefaultAsync(x => x.CAuid == selectUser.CAuid);
//null이면(없으면) add
if (findRefreshToken == null)
{
await context.AddAsync(new TRefreshToken
{
CAuid = selectUser.CAuid,
CRefreshToken = $"{RefreshToken}"
});
}
//있으면 update
else
{
findRefreshToken.CRefreshToken = $"{RefreshToken}";
context.Update(findRefreshToken);
}
//commit
Log4net.WriteLine(findRefreshToken?.ToJson(), LogType.Debug);
result = true;
}
catch (Exception ex)
{
Log4net.WriteLine(ex);
}
transactionResult = await context.CloseTransactionAsync(transaction);
}
}
else
{
Log4net.WriteLine($"Not Exist User {loginModel.UserID}", LogType.Error);
}
//db error
if (transactionResult == false)
{
Log4net.WriteLine($"Transaction Error", LogType.Error);
}
else
{
Log4net.WriteLine($"Transaction Success", LogType.DB);
}
}
}
}
return result;
}
public LogoutResponse LogoutUser(Logout logoutModel)
{
LogoutResponse response = new LogoutResponse();
response.UserID = logoutModel.UserID;
response.EC = ERROR_CODE.EC_USER_LOGOUT_FAILED;
var session = Session.Find(x => x.UserID?.ToLower() == logoutModel?.UserID?.ToLower());
if (session != null)
{
Session.Remove(session);
response.EC = ERROR_CODE.EC_OK;
}
return response;
}
private AccountDbContext? GetAccountDBContext(DbContextProvider provider, int dbID)
{
var connectionString = _configService?.GetConfig()?.DataBase?.Find(x => x.DBID == dbID);
return provider?.GetDBContext<AccountDbContext>($"{connectionString?.DBName}");
}
}
}