[성현모] DBProvider추가. LoginContext 변경

This commit is contained in:
SHM
2025-07-17 11:54:42 +09:00
parent 7a12be392a
commit 3c5f27ce68
22 changed files with 265 additions and 323 deletions

View File

@ -18,7 +18,6 @@
"Port": 1433, "Port": 1433,
"DBName": "AccountDB", "DBName": "AccountDB",
"DBID": 1, "DBID": 1,
"DBContext": "AccountDB",
"UserID": "SystemX", "UserID": "SystemX",
"Password": "X" "Password": "X"
}, },
@ -27,7 +26,6 @@
"Port": 1433, "Port": 1433,
"DBName": "AccountDB_DEV", "DBName": "AccountDB_DEV",
"DBID": 2, "DBID": 2,
"DBContext": "AccountDB",
"UserID": "SystemX", "UserID": "SystemX",
"Password": "X" "Password": "X"
} }

View File

@ -52,7 +52,7 @@
</mapping> </mapping>
<mapping> <mapping>
<level value="CONTROLLER" /> <level value="CONTROLLER" />
<foreColor value="DarkGreen" /> <foreColor value="Magenta" />
</mapping> </mapping>
</appender> </appender>

Binary file not shown.

View File

@ -1,16 +1,23 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using SystemX.Core.Config;
using SystemX.Core.Services; using SystemX.Core.Services;
using WebApi.Library.Config;
namespace AuthApi.Controllers namespace SystemX.Core.Controller
{ {
public class CommonController : ControllerBase public class CommonController<T> : ControllerBase where T : WebCommonConfig
{ {
public readonly IServiceProvider _serviceProvider; public readonly IServiceProvider _serviceProvider;
public readonly IHttpContextAccessor _httpContextAccessor; public readonly IHttpContextAccessor _httpContextAccessor;
public readonly ConfigService<WebApiConfig>? _configService; public readonly ConfigService<T>? _configService;
protected static Guid guid { get; private set; } = Guid.NewGuid(); protected static Guid guid { get; private set; } = Guid.NewGuid();
@ -21,7 +28,7 @@ namespace AuthApi.Controllers
_httpContextAccessor = httpContextAccessor; _httpContextAccessor = httpContextAccessor;
//service //service
_configService = _serviceProvider.GetService<ConfigService<WebApiConfig>>(); _configService = _serviceProvider.GetRequiredService<ConfigService<T>>();
} }
/// <summary> /// <summary>
@ -53,7 +60,7 @@ namespace AuthApi.Controllers
/// </summary> /// </summary>
protected virtual string GetMethodName([CallerMemberName] string callerMemberName = "") protected virtual string GetMethodName([CallerMemberName] string callerMemberName = "")
{ {
return callerMemberName; return $"{callerMemberName}()";
} }
} }
} }

View File

@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using SystemX.Core.DB.DBContext.AccountDB.Tables;
namespace SystemX.Core.DB.DBContext.AccountDB.Context;
public partial class AccountDbContext : DbContext
{
public AccountDbContext()
{
}
public AccountDbContext(DbContextOptions<AccountDbContext> options)
: base(options)
{
}
public virtual DbSet<TRefreshToken> TRefreshTokens { get; set; }
public virtual DbSet<TRole> TRoles { get; set; }
public virtual DbSet<TUser> TUsers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseSqlServer("server=127.0.0.1; user id=SystemX; password=X; database=AccountDB; TrustServerCertificate=true;");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TRefreshToken>(entity =>
{
entity.HasKey(e => e.CAuid).HasName("PK__tRefresh__FBF0855465EB95AB");
entity.ToTable("tRefreshToken");
entity.Property(e => e.CAuid)
.HasMaxLength(250)
.HasColumnName("cAuid");
entity.Property(e => e.CRefreshToken)
.HasMaxLength(1000)
.HasColumnName("cRefreshToken");
});
modelBuilder.Entity<TRole>(entity =>
{
entity.HasKey(e => e.CAuid).HasName("PK__tRole__FBF085540BB887D7");
entity.ToTable("tRole");
entity.Property(e => e.CAuid)
.HasMaxLength(250)
.HasColumnName("cAuid");
entity.Property(e => e.CRoleId).HasColumnName("cRoleID");
entity.Property(e => e.CRoleName)
.HasMaxLength(20)
.HasColumnName("cRoleName");
});
modelBuilder.Entity<TUser>(entity =>
{
entity.HasKey(e => e.CUserId).HasName("PK__tUser__A75DC19A721265FF");
entity.ToTable("tUser");
entity.Property(e => e.CUserId)
.HasMaxLength(50)
.HasColumnName("cUserID");
entity.Property(e => e.CAuid)
.HasMaxLength(250)
.HasColumnName("cAuid");
entity.Property(e => e.CCreateDateTime).HasColumnName("cCreateDateTime");
entity.Property(e => e.CLastLoginDateTime).HasColumnName("cLastLoginDateTime");
entity.Property(e => e.CPasswordHashed)
.HasMaxLength(250)
.HasColumnName("cPasswordHashed");
entity.Property(e => e.CState).HasColumnName("cState");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

View File

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
namespace SystemX.Core.DB.DBContext.AccountDB.Tables;
public partial class TRefreshToken
{
public string CAuid { get; set; } = null!;
public string CRefreshToken { get; set; } = null!;
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
namespace SystemX.Core.DB.DBContext.AccountDB.Tables;
public partial class TRole
{
public string CAuid { get; set; } = null!;
public byte CRoleId { get; set; }
public string CRoleName { get; set; } = null!;
}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
namespace SystemX.Core.DB.DBContext.AccountDB.Tables;
public partial class TUser
{
public string CUserId { get; set; } = null!;
public string CAuid { get; set; } = null!;
public string CPasswordHashed { get; set; } = null!;
public byte CState { get; set; }
public DateTime CCreateDateTime { get; set; }
public DateTime? CLastLoginDateTime { get; set; }
}

View File

@ -363,7 +363,7 @@ public static class Log4net
</mapping> </mapping>
<mapping> <mapping>
<level value=""CONTROLLER"" /> <level value=""CONTROLLER"" />
<foreColor value=""DarkGreen"" /> <foreColor value=""Magenta"" />
</mapping> </mapping>
</appender> </appender>

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace SystemX.Core.Model.Auth namespace SystemX.Core.Model.Auth
{ {
//로그인 요청 모델 //로그인 요청 모델
public class LoginModel public class Login
{ {
[Required] [Required]
public string? UserID { get; set; } public string? UserID { get; set; }
@ -19,7 +19,7 @@ namespace SystemX.Core.Model.Auth
} }
//로그인 응답 모델 //로그인 응답 모델
public class LoginResponseModel public class LoginResponse
{ {
public string? UserID { get; set; } public string? UserID { get; set; }
public UserRole Role { get; set; } public UserRole Role { get; set; }

View File

@ -8,13 +8,13 @@ using System.Threading.Tasks;
namespace SystemX.Core.Model.Auth namespace SystemX.Core.Model.Auth
{ {
public class LogoutModel public class Logout
{ {
[Required] [Required]
public string? UserID { get; set; } public string? UserID { get; set; }
} }
public class LogoutResponseModel public class LogoutResponse
{ {
public string? UserID { get; set; } public string? UserID { get; set; }

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace SystemX.Core.Model.Auth namespace SystemX.Core.Model.Auth
{ {
//유저 등록 모델 //유저 등록 모델
public class RegisterModel public class Register
{ {
[Required] [Required]
public string UserID { get; set; } = string.Empty; public string UserID { get; set; } = string.Empty;
@ -24,7 +24,7 @@ namespace SystemX.Core.Model.Auth
public UserRole Role { get; set; } = UserRole.User; public UserRole Role { get; set; } = UserRole.User;
} }
public class RegisterResponseModel public class RegisterResponse
{ {
public string? UserID { get; set; } public string? UserID { get; set; }
public UserRole Role { get; set; } public UserRole Role { get; set; }

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemX.Core.Model.Auth
{
public class UserModel
{
//public TUser? TUser { get; set; }
//public TRole? TRole { get; set; }
}
}

View File

@ -0,0 +1,45 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemX.Core.Config.Model;
namespace SystemX.Core.Services
{
public class DbContextProvider
{
private Dictionary<string, DataBase> DBDictionary = new Dictionary<string, DataBase>();
public void SetDBList(IList<DataBase>? DBList)
{
if (DBList?.Count > 0)
{
foreach (var db in DBList)
{
if (DBDictionary.ContainsKey($"{db.DBName}") == false)
DBDictionary.Add($"{db.DBName}", db);
else
Log4net.WriteLine($"Exist key DB Dictionary {db.DBName}", LogType.Error);
}
}
}
// 또는 context 직접 반환 (주의: caller가 Dispose 해야 함)
public TContext? GetDBContext<TContext>(string dbName) where TContext : DbContext
{
if(DBDictionary.TryGetValue(dbName, out var db) == true)
{
var optionsBuilder = new DbContextOptionsBuilder<TContext>();
optionsBuilder.UseSqlServer(db.ConvertToConnectionString());
return (TContext)Activator.CreateInstance(typeof(TContext), optionsBuilder.Options);
}
return null;
}
}
}

View File

@ -20,6 +20,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" /> <PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="log4net" Version="3.0.4" /> <PackageReference Include="log4net" Version="3.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.6"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.6">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -12,7 +12,7 @@ public static class DBUtils
/// </summary> /// </summary>
public static string ConvertToConnectionString(this DataBase dbConfig) public static string ConvertToConnectionString(this DataBase dbConfig)
{ {
return $"server={dbConfig.IP},{dbConfig.Port}; user id={dbConfig.UserID}; password={dbConfig.Password}; database={dbConfig.DBName};"; return $"server={dbConfig.IP},{dbConfig.Port}; user id={dbConfig.UserID}; password={dbConfig.Password}; database={dbConfig.DBName}; TrustServerCertificate=True;";
} }
} }

View File

@ -1,6 +0,0 @@
@AuthApi_HostAddress = http://localhost:5177
GET {{AuthApi_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -1,4 +1,5 @@
using AuthApi.Services; using AuthApi.Services;
using Azure.Core;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
@ -6,15 +7,17 @@ using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims; using System.Security.Claims;
using System.Text; using System.Text;
using SystemX.Core; using SystemX.Core;
using SystemX.Core.Controller;
using SystemX.Core.Model.Auth; using SystemX.Core.Model.Auth;
using WebApi.Library.Config;
namespace AuthApi.Controllers namespace AuthApi.Controllers
{ {
[Tags("Auth")] [Tags("Auth")]
[Route("api/auth")] [Route("api/auth")]
[ApiController] [ApiController]
[ApiExplorerSettings(IgnoreApi = true)] [ApiExplorerSettings(IgnoreApi = false)]
public class AuthController : CommonController public class AuthController : CommonController<WebApiConfig>
{ {
private readonly AuthService _authService; private readonly AuthService _authService;
@ -25,36 +28,39 @@ namespace AuthApi.Controllers
_authService = authService; _authService = authService;
} }
[HttpGet("/health")] [HttpGet("health")]
public async Task<IResult> Health() public async Task<IResult> Health()
{ {
Log4net.WriteLine($"[{GetRequestMethod()}:{GetMethodName()}] [Client IP:{GetClientIP()}] [RequestUrl:{GetRequestUrl()}]{Environment.NewLine}", LogType.CONTROLLER);
await Task.CompletedTask; await Task.CompletedTask;
return Results.Ok("Healthy"); return Results.Ok("Healthy");
} }
[HttpPost("regisger")] [HttpPost("regisger")]
public async Task<IResult> Register([FromBody] RegisterModel request) public async Task<IResult> Register([FromBody] Register request)
{ {
// Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.CONTROLLER); Guid guid = Guid.NewGuid();
RegisterResponseModel response = new RegisterResponseModel(); Log4net.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogType.CONTROLLER);
RegisterResponse response = new RegisterResponse();
if (request?.UserID != null && request?.Password != null) if (request?.UserID != null && request?.Password != null)
{ {
response = await _authService.CreateUser(request); response = await _authService.CreateUser(request);
} }
// Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.CONTROLLER); Log4net.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogType.CONTROLLER);
return Results.Ok(response); return Results.Ok(response);
} }
[HttpPost("login")] [HttpPost("login")]
public async Task<IResult> Login([FromBody] LoginModel request) public async Task<IResult> Login([FromBody] Login request)
{ {
// Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.CONTROLLER); Log4net.WriteLine($"[Request]({guid}) api/auth/register{Environment.NewLine} {request.ToJson()}", LogType.CONTROLLER);
LoginResponseModel response = new LoginResponseModel(); LoginResponse response = new LoginResponse();
response.UserID = request.UserID; response.UserID = request.UserID;
response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED; response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED;
@ -75,20 +81,20 @@ namespace AuthApi.Controllers
await _authService.UpdateLoginInfo(request, response.RefreshToken); await _authService.UpdateLoginInfo(request, response.RefreshToken);
} }
// Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.CONTROLLER); Log4net.WriteLine($"[Response]({guid}) api/auth/register{Environment.NewLine} {response.ToJson()}", LogType.CONTROLLER);
return Results.Ok(response); return Results.Ok(response);
} }
[HttpPost("logout")] [HttpPost("logout")]
public async Task<IResult> Logout([FromBody] LogoutModel request) public async Task<IResult> Logout([FromBody] Logout request)
{ {
// Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.CONTROLLER); Log4net.WriteLine($"[Request]({guid}) api/auth/register{Environment.NewLine} {request.ToJson()}", LogType.CONTROLLER);
var response = _authService.LogoutUser(request); var response = _authService.LogoutUser(request);
await Task.CompletedTask; await Task.CompletedTask;
// Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.CONTROLLER); Log4net.WriteLine($"[Response]({guid}) api/auth/register{Environment.NewLine} {response.ToJson()}", LogType.CONTROLLER);
return Results.Ok(response); return Results.Ok(response);
} }
@ -113,7 +119,7 @@ namespace AuthApi.Controllers
}; };
} }
private string GenerateJwtToken(LoginResponseModel loginResponseModel, bool isRefreshToken = false) private string GenerateJwtToken(LoginResponse loginResponseModel, bool isRefreshToken = false)
{ {
var claims = new[] var claims = new[]
{ {

View File

@ -1,10 +1,14 @@
using AuthApi.Services; using AuthApi.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Text; using System.Text;
using SystemX.Core.Services; using SystemX.Core.Services;
using WebApi.Library.Config; using WebApi.Library.Config;
using WebApi.Library.DBContext.DB.DBContext.AccountDB.Context;
string configDir = @"../../Config"; string configDir = @"../../Config";
string configFileName = "WebApi.AuthApi.Config.json"; string configFileName = "WebApi.AuthApi.Config.json";
@ -26,14 +30,18 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
//singleton //singleton
builder.Services.AddSingleton<ConfigService<WebApiConfig>>(); builder.Services.AddSingleton<ConfigService<WebApiConfig>>();
builder.Services.AddScoped<AuthService>();
//scoped //scoped
builder.Services.AddScoped<AuthService>();
//db
builder.Services.AddSingleton<DbContextProvider>(); // Generic <20><><EFBFBD><EFBFBD>
builder.Services.AddControllers(); builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); builder.Services.AddSwaggerGen();
builder.Services.AddHttpContextAccessor();
//config preload, auth set //config preload, auth set
ConfigService<WebApiConfig> preloadConfig = new ConfigService<WebApiConfig>(); ConfigService<WebApiConfig> preloadConfig = new ConfigService<WebApiConfig>();
@ -84,6 +92,24 @@ if (configService?.OpenConfig($@"{configDir}/{configFileName}") == true)
{ {
serverUrl = $"{apiConfig?.Server?.Address}:{apiConfig?.Server?.Port}"; serverUrl = $"{apiConfig?.Server?.Address}:{apiConfig?.Server?.Port}";
isIIS = apiConfig!.Server.IIS; isIIS = apiConfig!.Server.IIS;
using(var scoped = app.Services.CreateScope())
{
var dbProvider = scoped.ServiceProvider.GetRequiredService<DbContextProvider>();
dbProvider?.SetDBList(apiConfig?.DataBase);
}
//dbcontext set
//app.Use(async (context, next) =>
//{
// var dbProvider = context.RequestServices.GetService<DbContextProvider>();
// // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// dbProvider?.SetDBList(apiConfig?.DataBase);
// await next.Invoke();
//});
//var dbProviderService = app.Services.GetService<DbContextProvider>();
//dbProviderService?.SetDBList(apiConfig?.DataBase);
} }
} }
else else

View File

@ -6,8 +6,8 @@ using SystemX.Core.Config.Model;
using System.Data; using System.Data;
using SystemX.Core.DB; using SystemX.Core.DB;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using SystemX.Core.DB.DBContext.AccountDB.Context; using WebApi.Library.DBContext.DB.DBContext.AccountDB.Context;
using SystemX.Core.DB.DBContext.AccountDB.Tables; using WebApi.Library.DBContext.DB.DBContext.AccountDB.Tables;
namespace AuthApi.Services namespace AuthApi.Services
{ {
@ -17,25 +17,21 @@ namespace AuthApi.Services
private readonly IServiceScopeFactory _scopeFactory; private readonly IServiceScopeFactory _scopeFactory;
private readonly ConfigService<WebApiConfig>? _configService; private readonly ConfigService<WebApiConfig>? _configService;
private readonly DataBase? _accountDB; private static List<LoginResponse> Session = new List<LoginResponse>();
private static List<LoginResponseModel> Session = new List<LoginResponseModel>();
public AuthService(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, ConfigService<WebApiConfig> configSerice) public AuthService(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, ConfigService<WebApiConfig> configSerice)
{ {
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_configService = configSerice; _configService = configSerice;
_scopeFactory = scopeFactory; _scopeFactory = scopeFactory;
_accountDB = _configService?.GetConfig()?.DataBase?.Find(x => x.DBContext == "VpkiAccountDbContext");
} }
/// <summary> /// <summary>
/// create new user /// create new user
/// </summary> /// </summary>
public async Task<RegisterResponseModel> CreateUser(RegisterModel registerModel) public async Task<RegisterResponse> CreateUser(Register registerModel)
{ {
//response RegisterResponse response = new RegisterResponse();
RegisterResponseModel response = new RegisterResponseModel();
response.EC = ERROR_CODE.EC_USER_REGISTER_FAILED; response.EC = ERROR_CODE.EC_USER_REGISTER_FAILED;
response.UserID = registerModel.UserID; response.UserID = registerModel.UserID;
response.Role = registerModel.Role; response.Role = registerModel.Role;
@ -44,39 +40,42 @@ namespace AuthApi.Services
//context //context
using (var scope = _scopeFactory.CreateScope()) using (var scope = _scopeFactory.CreateScope())
{ {
var context = scope.ServiceProvider.GetRequiredService<AccountDbContext>(); var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
if (context is not null) using (var context = GetAccountDBContext(provider, 1))
{ {
var user = await context.TUsers.AsNoTracking().Where(x => x.CUserId.ToLower() == registerModel.UserID.ToLower()).ToListAsync(); if (context is not null)
if (user?.Count <= 0)
{ {
string auid = Guid.NewGuid().ToString(); var user = await context.TUsers.AsNoTracking().Where(x => x.CUserId.ToLower() == registerModel.UserID.ToLower()).ToListAsync();
//user if (user?.Count <= 0)
TUser newUser = new TUser
{ {
CAuid = auid, string auid = Guid.NewGuid().ToString();
CUserId = registerModel.UserID, //user
CPasswordHashed = registerModel.Password, TUser newUser = new TUser
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; 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;
}
} }
} }
} }
@ -89,80 +88,82 @@ namespace AuthApi.Services
/// <summary> /// <summary>
/// select user(login) /// select user(login)
/// </summary> /// </summary>
public async Task<LoginResponseModel> SelectUser(LoginModel loginModel) public async Task<LoginResponse> SelectUser(Login loginModel)
{ {
//response //response
LoginResponseModel response = new LoginResponseModel(); LoginResponse response = new LoginResponse();
response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED; response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED;
response.UserID = loginModel.UserID; response.UserID = loginModel.UserID;
//var session = Session.Find(x => x.UserID?.ToLower() == loginModel.UserID?.ToLower()); var session = Session.Find(x => x.UserID?.ToLower() == loginModel.UserID?.ToLower());
//if (session?.AccessTokenExpired < DateTime.Now.ToUnixTime()) if (session?.AccessTokenExpired < DateTime.Now.ToUnixTime())
//{ {
// Session.Remove(session); Session.Remove(session);
//} }
//기존 로그인 체크 //기존 로그인 체크
// if (Session.Exists(x => x.UserID == $"{loginModel.UserID?.ToLower()}") == false) if (Session.Exists(x => x.UserID == $"{loginModel.UserID?.ToLower()}") == false)
{ {
if (loginModel != null) if (loginModel != null)
{ {
//context //context
using (var scope = _scopeFactory.CreateScope()) using (var scope = _scopeFactory.CreateScope())
{ {
var context = scope.ServiceProvider.GetRequiredService<AccountDbContext>(); var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
if (context is not null) using (var context = GetAccountDBContext(provider, 1))
{ {
try if (context is not null)
{ {
using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted)) try
{ {
//select user using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted))
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 user
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
{ {
//select role if (selectUser.CPasswordHashed == loginModel?.Password)
var selectRole = await context.TRoles.FindAsync(selectUser.CAuid);
if (selectRole != null)
{ {
response.Role = (UserRole)Enum.Parse(typeof(UserRole), selectRole.CRoleId.ToString()); //select role
response.RoleName = selectRole.CRoleName; 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); Session.Add(response);
if (selectUser.CState == (byte)UserState.Active)
if (selectUser.CState == (byte)UserState.Active) {
{ response.EC = ERROR_CODE.EC_OK;
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 if (selectUser.CState == (byte)UserState.Inactive) else
{ {
response.EC = ERROR_CODE.EC_USER_LOGIN_INAVTIVE; response.EC = ERROR_CODE.EC_USER_LOGIN_INVALID_PASSWORD;
}
else if (selectUser.CState == (byte)UserState.Block)
{
response.EC = ERROR_CODE.EC_USER_LOGIN_BLOCKED;
} }
} }
else else
{ {
response.EC = ERROR_CODE.EC_USER_LOGIN_INVALID_PASSWORD; response.EC = ERROR_CODE.EC_USER_LOGIN_NOT_EXIST;
Log4net.WriteLine($"{response.EC}", LogType.Error);
} }
await context.CloseTransactionAsync(transaction);
} }
else
{
response.EC = ERROR_CODE.EC_USER_LOGIN_NOT_EXIST;
Log4net.WriteLine($"{response.EC}", LogType.Error);
}
await context.CloseTransactionAsync(transaction);
} }
} catch (Exception e)
catch (Exception e) {
{ Log4net.WriteLine($"Select User Transaction Error", LogType.Exception);
Log4net.WriteLine($"Select User Transaction Error", LogType.Exception); Log4net.WriteLine(e);
Log4net.WriteLine(e); }
} }
} }
} }
@ -172,71 +173,74 @@ namespace AuthApi.Services
return response; return response;
} }
public async Task<bool> UpdateLoginInfo(LoginModel loginModel, string? RefreshToken = "") public async Task<bool> UpdateLoginInfo(Login loginModel, string? RefreshToken = "")
{ {
bool result = false; bool result = false;
bool transactionResult = true; bool transactionResult = true;
using (var scope = _scopeFactory.CreateScope()) using (var scope = _scopeFactory.CreateScope())
{ {
var context = scope.ServiceProvider.GetRequiredService<AccountDbContext>(); var provider = scope.ServiceProvider.GetRequiredService<DbContextProvider>();
if (context is not null) using (var context = GetAccountDBContext(provider, 1))
{ {
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower()); if (context is not null)
if (selectUser is not null)
{ {
using (var transaction = await context.CreateTransactionAsync()) var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
if (selectUser is not null)
{ {
try using (var transaction = await context.CreateTransactionAsync())
{ {
//user info try
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 //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)
{ {
CAuid = selectUser.CAuid, await context.AddAsync(new TRefreshToken
CRefreshToken = $"{RefreshToken}" {
}); CAuid = selectUser.CAuid,
CRefreshToken = $"{RefreshToken}"
});
}
//있으면 update
else
{
findRefreshToken.CRefreshToken = $"{RefreshToken}";
context.Update(findRefreshToken);
}
//commit
Log4net.WriteLine(findRefreshToken?.ToJson(), LogType.Debug);
result = true;
} }
//있으면 update catch (Exception ex)
else
{ {
findRefreshToken.CRefreshToken = $"{RefreshToken}"; Log4net.WriteLine(ex);
context.Update(findRefreshToken);
} }
//commit transactionResult = await context.CloseTransactionAsync(transaction);
Log4net.WriteLine(findRefreshToken?.ToJson(), LogType.Debug);
result = true;
} }
catch (Exception ex)
{
Log4net.WriteLine(ex);
}
transactionResult = await context.CloseTransactionAsync(transaction);
} }
} else
else {
{ Log4net.WriteLine($"Not Exist User {loginModel.UserID}", LogType.Error);
Log4net.WriteLine($"Not Exist User {loginModel.UserID}", LogType.Error); }
}
//db error //db error
if (transactionResult == false) if (transactionResult == false)
{ {
Log4net.WriteLine($"Transaction Error", LogType.Error); Log4net.WriteLine($"Transaction Error", LogType.Error);
} }
else else
{ {
Log4net.WriteLine($"Transaction Success", LogType.DB); Log4net.WriteLine($"Transaction Success", LogType.DB);
}
} }
} }
} }
@ -244,9 +248,9 @@ namespace AuthApi.Services
return result; return result;
} }
public LogoutResponseModel LogoutUser(LogoutModel logoutModel) public LogoutResponse LogoutUser(Logout logoutModel)
{ {
LogoutResponseModel response = new LogoutResponseModel(); LogoutResponse response = new LogoutResponse();
response.UserID = logoutModel.UserID; response.UserID = logoutModel.UserID;
response.EC = ERROR_CODE.EC_USER_LOGOUT_FAILED; response.EC = ERROR_CODE.EC_USER_LOGOUT_FAILED;
@ -259,5 +263,11 @@ namespace AuthApi.Services
return response; 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}");
}
} }
} }

View File

@ -22,10 +22,6 @@ public partial class AccountDbContext : DbContext
public virtual DbSet<TUser> TUsers { get; set; } public virtual DbSet<TUser> TUsers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseSqlServer("server=127.0.0.1; user id=SystemX; password=X; database=AccountDB; TrustServerCertificate=true;");
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.Entity<TRefreshToken>(entity => modelBuilder.Entity<TRefreshToken>(entity =>