diff --git a/Program.cs b/Program.cs index 0d76037..2b69b6f 100644 --- a/Program.cs +++ b/Program.cs @@ -123,8 +123,12 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); // builder.Services.AddScoped(); // // builder.Services.AddScoped(); diff --git a/Program/Controllers/V1/AppController.cs b/Program/Controllers/V1/AppController.cs index c415f68..4d53461 100644 --- a/Program/Controllers/V1/AppController.cs +++ b/Program/Controllers/V1/AppController.cs @@ -5,7 +5,9 @@ using Back.Program.Common.Auth; using Back.Program.Common.Data; using Back.Program.Common.Model; using Back.Program.Models.Entities; +using Back.Program.Repositories.V1.Interfaces; using Back.Program.Services.V1; +using Back.Program.Services.V1.Interfaces; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Version = Back.Program.Models.Entities.Version; @@ -21,13 +23,17 @@ namespace Back.Program.Controllers.V1 private readonly ILogger _logger; private readonly IRepositoryService _repositoryService; private readonly JwtTokenService _jwtTokenService; + private readonly IAppService _appService; + private readonly IAppRepository _appRepository; - public AppController(AppDbContext dbContext, ILogger logger, IRepositoryService repositoryService, JwtTokenService jwtTokenService) + public AppController(AppDbContext dbContext, ILogger logger, IRepositoryService repositoryService, JwtTokenService jwtTokenService,IAppService appService, IAppRepository appRepository) { _dbContext = dbContext; _logger = logger; _repositoryService = repositoryService; _jwtTokenService = jwtTokenService; + _appService = appService; + _appRepository = appRepository; } @@ -39,228 +45,30 @@ namespace Back.Program.Controllers.V1 if (string.IsNullOrEmpty(specific) || string.IsNullOrEmpty(type) || string.IsNullOrEmpty(project)) return BadRequest(APIResponse.InvalidInputError()); if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - string summary = String.Empty; + string summary = _repositoryService.ReadSummary(typeof(AppController), "GetHeaderValue"); - try - { - summary = _repositoryService.ReadSummary(typeof(AppController), "GetHeaderValue"); - bool valid = false; - - switch (type) - { - case "I": - if (project == "me.myds.ipstein.acamate.AcaMate") valid = true; - break; - case "A": - break; - case "W": - break; - default: - return BadRequest(APIResponse.InvalidInputError($"[{summary}], 타입 에러")); - break; - } - - if (valid) - { - - var apiHeader = await _dbContext.APIHeader.FirstOrDefaultAsync(h => h.specific_id == specific); - - string nowTime = DateTime.Now.ToString("o"); - string combineText = $"{project}_{nowTime}_{specific}"; - string headerValue = KeyGenerator(combineText); - - if (apiHeader != null) - { - if (DateTime.Now - apiHeader.connect_date > TimeSpan.FromHours(24)) - { - _logger.LogInformation($"[{summary}] : 해당 키 유효기간 경과"); - apiHeader.h_value = headerValue; - apiHeader.connect_date = DateTime.Now; - - if (await _repositoryService.SaveData(apiHeader)) - { - string msg = "정상 - 로그 저장 실패"; - var logProject = new LogProject - { - create_date = DateTime.Now , - log = $"[{summary}] : 해당 키 유효시간 만료로 인한 새 키 부여" - }; - if (await _repositoryService.SaveData(logProject)) - msg = "정상"; - return Ok(APIResponse.Send("001", msg, new { header = headerValue })); - } - else - { - // 저장이 안된거니 서버 오류 - return StatusCode(500, APIResponse.InternalSeverError()); - } - } - else - { - // 유효기간 만료 이상 없이 다 잘 됨 - return Ok(APIResponse.Send("000", "정상", new { header = apiHeader.h_value })); - } - } - else - { - _logger.LogInformation($"[{summary}] : 저장 된게 없음"); - - var newHeader = new APIHeader - { - h_key = type == "I" ? "iOS_AM_Connect_Key" - : (type == "A" ? "And_AM_Connect_Key" - : (type == "W" ? "Web_AM_Connect_Key": throw new Exception("ERROR"))), - h_value = headerValue, - connect_date = DateTime.Now, - specific_id = specific - }; - - if (await _repositoryService.SaveData(newHeader)) - { - string msg = "정상 - 로그 저장 실패"; - var logProject = new LogProject - { - create_date = DateTime.Now , - log = $"[{summary}] : 새로운 등록으로 인한 새 키 부여" - }; - // 이거 로그 저장 안되는거 확인! - _logger.LogInformation($"[{summary}] : {logProject.log}"); - if (await _repositoryService.SaveData(logProject)) - msg = "정상"; - - return Ok(APIResponse.Send("001", msg, new { header = headerValue })); - } - else - { - // 저장이 안된거니 서버 오류 - return StatusCode(500, APIResponse.InternalSeverError()); - } - } - } - return BadRequest(APIResponse.InvalidInputError()); - - - // return Ok(APIResponse.Send("000", "정상", Empty)); - } - catch (Exception ex) - { - _logger.LogError($"[{summary}] : {ex.Message}"); - return StatusCode(500, APIResponse.UnknownError(ex.Message)); - } - } - - // 스웨거는 퍼블릭으로 선언된걸 죄다 API로 인식하는 경향이 있음 - // 방법은 private 같이 접근 제한자를 변경하거나 [NonAction]을 붙여주면 됨 - [NonAction] - private string KeyGenerator(string combineText) - { - using (SHA256 sha256 = SHA256.Create()) - { - byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combineText)); - return BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLowerInvariant(); - } + var result = await _appService.GetHeader(summary, type, specific, project); + return Ok(result); } [HttpGet("version")] [CustomOperation("앱 버전 확인","앱 버전을 확인해서 업데이트 여부 판단", "시스템")] public async Task GetVersionData(string type) { - if (string.IsNullOrEmpty(type)) - { - return BadRequest(APIResponse.InvalidInputError()); - } - - try - { - var version = await _dbContext.Version.FirstOrDefaultAsync(v => v.os_type == (type == "I" ? "VO01" : "VO02")); - - if (version == null) - { - return NotFound(APIResponse.NotFoundError()); - } - - var response = new APIResponseStatus - { - status = new Status() - { - code = "000", - message = "정상" - }, - data = new Version() - { - os_type = (version.os_type == "VO01" ? "I" : (version.os_type == "VO02" ? "A" : "W")), - final_ver = version.final_ver, - force_ver = version.force_ver, - dev_ver = version.dev_ver, - choice_update_yn = version.choice_update_yn - } - }; - - string jsonString = JsonSerializer.Serialize(response); - - // return Ok(jsonString); - return Ok(response.JsonToString()); - } - catch (Exception ex) - { - Console.WriteLine($"{ex.Message}\n{ex.StackTrace}"); - return StatusCode(500, APIResponse.UnknownError()); - } + if (string.IsNullOrEmpty(type)) return BadRequest(APIResponse.InvalidInputError()); + string summary = _repositoryService.ReadSummary(typeof(AppController), "GetHeaderValue"); + var result = await _appService.GetVersion(summary, type); + return Ok(result); } - - - [HttpGet("auth")] - [CustomOperation("서버 접근 권한 확인", "서버 기능을 사용하기 위한 접근에 대해 권한 확인", "시스템")] - public async Task AuthProgram([FromBody] AuthKey keys) - { - string summary = String.Empty; - - try - { - summary = _repositoryService.ReadSummary(typeof(AppController), "AuthProgram"); - } - catch (Exception ex) - { - _logger.LogError($"[{summary}] : {ex.Message}"); - return StatusCode(500, APIResponse.UnknownError(ex.Message)); - } - - return Ok(APIResponse.Send("000", "OK", Empty)); - } - - + [HttpGet("retryAccess")] [CustomOperation("엑세스 토큰 재발급", "액세스 토큰 재발급 동작 수행", "시스템")] public async Task RetryAccessToken(string refresh) { - string summary = String.Empty; - - try - { - summary = _repositoryService.ReadSummary(typeof(AppController), "AuthProgram"); - var refreshToken = await _dbContext.RefreshToken - .FirstOrDefaultAsync(t => t.refresh_token == refresh); - if (refreshToken == null) throw new TokenException($"[{summary}] : 리프레시 토큰의 문제"); - if (refreshToken.revoke_Date < DateTime.Now) throw new TokenException($"[{summary}] : 리프레시 토큰 만료"); - if (refreshToken.expire_date < DateTime.Now) throw new TokenException($"[{summary}] : 리프레시 토큰 폐기"); - string access = _jwtTokenService.GenerateJwtToken(refreshToken.uid); - return Ok(APIResponse.Send("000", $"[{summary}], 토큰 생성 완료", - new { - access = access - })); - } - catch (TokenException ex) - { - _logger.LogError($"[{summary}] : {ex.Message}"); - return Ok(APIResponse.InvalidInputError(ex.Message)); - } - catch (Exception ex) - { - _logger.LogError($"[{summary}] : {ex.Message}"); - return StatusCode(500, APIResponse.UnknownError(ex.Message)); - } - - + if (string.IsNullOrEmpty(refresh)) return BadRequest(APIResponse.InvalidInputError()); + string summary = _repositoryService.ReadSummary(typeof(AppController), "RetryAccessToken"); + var result = await _appService.RetryAccess(summary, refresh); + return Ok(result); } diff --git a/Program/Controllers/V1/UserController.cs b/Program/Controllers/V1/UserController.cs index e811a91..c03420e 100644 --- a/Program/Controllers/V1/UserController.cs +++ b/Program/Controllers/V1/UserController.cs @@ -51,7 +51,7 @@ namespace Back.Program.Controllers.V1 if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); string summary = _repositoryService.ReadSummary(typeof(UserController), "GetUserData"); - var result = _userService.GetUser(summary, token); + var result = await _userService.GetUser(summary, token); return Ok(result); } @@ -77,7 +77,7 @@ namespace Back.Program.Controllers.V1 if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); string summary = _repositoryService.ReadSummary(typeof(UserController), "UserRegister"); - var result = _userService.Register(summary, request); + var result = await _userService.Register(summary, request); return Ok(result); } @@ -114,7 +114,7 @@ namespace Back.Program.Controllers.V1 if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); string summary = _repositoryService.ReadSummary(typeof(UserController), "ReadAcademyInfo"); - var result = _userService.GetAcademy(summary, token); + var result = await _userService.GetAcademy(summary, token); return Ok(result); } } diff --git a/Program/Repositories/V1/AppRepository.cs b/Program/Repositories/V1/AppRepository.cs new file mode 100644 index 0000000..d623422 --- /dev/null +++ b/Program/Repositories/V1/AppRepository.cs @@ -0,0 +1,35 @@ +using Back.Program.Common.Data; +using Back.Program.Common.Model; +using Back.Program.Models.Entities; +using Back.Program.Repositories.V1.Interfaces; + +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Version = Back.Program.Models.Entities.Version; + +namespace Back.Program.Repositories.V1; + +public class AppRepository: IAppRepository +{ + private readonly AppDbContext _context; + + public AppRepository(AppDbContext context) + { + _context = context; + } + + public async Task FindHeader(string specific) + { + return await _context.APIHeader.FirstOrDefaultAsync(h => h.specific_id == specific); + } + + public async Task FindVersion(string type) + { + return await _context.Version.FirstOrDefaultAsync(v => v.os_type == (type =="I" ? "VO01" : "VO02")); + } + + public async Task FindRefreshToken(string refresh) + { + return await _context.RefreshToken.FirstOrDefaultAsync(r => r.refresh_token == refresh); + } +} \ No newline at end of file diff --git a/Program/Repositories/V1/Interfaces/IAppRepository.cs b/Program/Repositories/V1/Interfaces/IAppRepository.cs new file mode 100644 index 0000000..3e71f44 --- /dev/null +++ b/Program/Repositories/V1/Interfaces/IAppRepository.cs @@ -0,0 +1,11 @@ +using Back.Program.Common.Model; +using Version = Back.Program.Models.Entities.Version; + +namespace Back.Program.Repositories.V1.Interfaces; + +public interface IAppRepository +{ + Task FindHeader(string specific); + Task FindVersion(string type); + Task FindRefreshToken(string refresh); +} \ No newline at end of file diff --git a/Program/Repositories/V1/Interfaces/ILogRepository.cs b/Program/Repositories/V1/Interfaces/ILogRepository.cs index d8d1ff8..7b526af 100644 --- a/Program/Repositories/V1/Interfaces/ILogRepository.cs +++ b/Program/Repositories/V1/Interfaces/ILogRepository.cs @@ -5,4 +5,5 @@ namespace Back.Program.Repositories.V1.Interfaces; public interface ILogRepository { Task SaveLogUser(LogUser log); + Task SaveLogProjrct(LogProject log); } \ No newline at end of file diff --git a/Program/Repositories/V1/LogRepository.cs b/Program/Repositories/V1/LogRepository.cs index d8430e3..396e968 100644 --- a/Program/Repositories/V1/LogRepository.cs +++ b/Program/Repositories/V1/LogRepository.cs @@ -21,4 +21,10 @@ public class LogRepository: ILogRepository _context.LogUser.Add(log); return await _context.SaveChangesAsync() > 0; } + + public async Task SaveLogProjrct(LogProject log) + { + _context.LogProject.Add(log); + return await _context.SaveChangesAsync() > 0; + } } \ No newline at end of file diff --git a/Program/Services/V1/AppService.cs b/Program/Services/V1/AppService.cs new file mode 100644 index 0000000..ae6922b --- /dev/null +++ b/Program/Services/V1/AppService.cs @@ -0,0 +1,167 @@ +using System.Security.Cryptography; +using System.Text; +using Back.Program.Common.Auth; +using Back.Program.Common.Model; +using Back.Program.Models.Entities; +using Back.Program.Repositories.V1.Interfaces; +using Back.Program.Services.V1.Interfaces; +using Version = Back.Program.Models.Entities.Version; + +namespace Back.Program.Services.V1; + +public class AppService: IAppService +{ + private readonly ILogger _logger; + private readonly IRepositoryService _repositoryService; + private readonly JwtTokenService _jwtTokenService; + private readonly ILogRepository _logRepository; + private readonly IAppRepository _appRepository; + + public AppService(ILogger logger, IRepositoryService repositoryService, + JwtTokenService jwtTokenService, ILogRepository logRepository, IAppRepository appRepository) + { + _logger = logger; + _repositoryService = repositoryService; + _jwtTokenService = jwtTokenService; + _logRepository = logRepository; + _appRepository = appRepository; + } + + public async Task> GetHeader(string summary, string type, string specific, string project) + { + bool valid = false; + switch (type) + { + case "I": + if (project == "me.myds.ipstein.acamate.AcaMate") valid = true; + break; + case "A": + break; + case "W": + break; + default: + return APIResponse.InvalidInputError($"[{summary}], 타입 에러"); + break; + } + + if (valid) + { + var apiHeader = await _appRepository.FindHeader(specific); + + string nowTime = DateTime.Now.ToString("o"); + string combineText = $"{project}_{nowTime}_{specific}"; + string headerValue = KeyGenerator(combineText); + if (apiHeader != null) + { + if (DateTime.Now - apiHeader.connect_date > TimeSpan.FromHours(24)) + { + _logger.LogInformation($"[{summary}] : 해당 키 유효기간 경과"); + apiHeader.h_value = headerValue; + apiHeader.connect_date = DateTime.Now; + if (await _repositoryService.SaveData(apiHeader)) + { + // 새로 업뎃해서 저장 + if(await _logRepository.SaveLogProjrct( new LogProject { create_date = DateTime.Now , log = $"[{summary}] : 해당 키 유효시간 만료로 인한 새 키 부여"})) + { + _logger.LogInformation($"[{summary}] : 성공"); + } + else + { + _logger.LogInformation($"[{summary}] : 성공 - 로그 저장 실패 "); + } + return APIResponse.Send("000", $"[{summary}], 정상", new { header = headerValue }); + } + else + { + // 저장이 안되었다? == 서버 오류 + return APIResponse.InternalSeverError(); + } + } + else + { + return APIResponse.Send("000", $"[{summary}], 정상", new { header = apiHeader.h_value }); + // 유효기간 경과도 없고 정상적으로 잘 불러짐 + } + } + else + { + // API 저장된 거 없으니 저장 합시다. + var newHeader = new APIHeader + { + h_key = type == "I" ? "iOS_AM_Connect_Key" + : (type == "A" ? "And_AM_Connect_Key" + : (type == "W" ? "Web_AM_Connect_Key": throw new Exception("ERROR"))), + h_value = headerValue, + connect_date = DateTime.Now, + specific_id = specific + }; + + if (await _repositoryService.SaveData(newHeader)) + { + // 새로 업뎃해서 저장 + if(await _logRepository.SaveLogProjrct( new LogProject { create_date = DateTime.Now , log = $"[{summary}] : 새 기기 등록으로 인한 새 키 부여"})) + { + _logger.LogInformation($"[{summary}] : 성공"); + } + else + { + _logger.LogInformation($"[{summary}] : 성공 - 로그 저장 실패 "); + } + return APIResponse.Send("000", $"[{summary}], 정상", new { header = headerValue }); + } + else + { + // 저장이 안되었다? == 서버 오류 + return APIResponse.InternalSeverError(); + } + } + } + else + { + // 헤더 없단 소리 == 문제 있음 + return APIResponse.InvalidInputError(); + } + } + + private string KeyGenerator(string combineText) + { + using (SHA256 sha256 = SHA256.Create()) + { + byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combineText)); + return BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLowerInvariant(); + } + } + + + public async Task> GetVersion(string summary, string type) + { + var version = await _appRepository.FindVersion(type); + if (version != null) + { + var sendVersion = new Version { + os_type = (version.os_type == "VO01" ? "I" : (version.os_type == "VO02" ? "A" : "W")), + final_ver = version.final_ver, + force_ver = version.force_ver, + dev_ver = version.dev_ver, + choice_update_yn = version.choice_update_yn + }; + return APIResponse.Send("000", $"[{summary}], 정상", sendVersion); + } + else + { + return APIResponse.NotFoundError(); + } + } + + public async Task> RetryAccess(string summary, string refresh) + { + var refreshToken = await _appRepository.FindRefreshToken(refresh); + if (refreshToken == null) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 문제"); + if (refreshToken.revoke_Date < DateTime.Now) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 만료"); + if (refreshToken.expire_date < DateTime.Now) return APIResponse.InvalidInputError($"[{summary}] : 리프레시 토큰 폐기"); + + string access = _jwtTokenService.GenerateJwtToken(refreshToken.uid); + return APIResponse.Send("000", $"[{summary}], 토큰 생성 완료", new { accsee = access }); + } + +} \ No newline at end of file diff --git a/Program/Services/V1/Interfaces/IAppService.cs b/Program/Services/V1/Interfaces/IAppService.cs new file mode 100644 index 0000000..94215e3 --- /dev/null +++ b/Program/Services/V1/Interfaces/IAppService.cs @@ -0,0 +1,11 @@ +using Back.Program.Common.Model; + +namespace Back.Program.Services.V1.Interfaces; + +public interface IAppService +{ + Task> GetHeader(string summary, string type, string specific, string project); + Task> GetVersion(string summary, string type); + Task> RetryAccess(string summary, string refresh); + +} \ No newline at end of file