AcaMate_API/Program/V1/Controllers/AppController.cs
Seonkyu_Kim 5994c9dc2f Merge remote-tracking branch 'origin/main'
# Conflicts:
#	Program/V1/Controllers/AppController.cs
2025-03-28 14:12:47 +09:00

272 lines
11 KiB
C#

using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;
using System.Security.Cryptography;
using System.Text;
using AcaMate.Common.Data;
using AcaMate.Common.Models;
using AcaMate.Common.Token;
using AcaMate.V1.Models;
using AcaMate.V1.Services;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Version = AcaMate.V1.Models.Version;
namespace AcaMate.V1.Controllers;
[ApiController]
[Route("/api/v1/in/app")]
[ApiExplorerSettings(GroupName = "공통")]
public class AppController : ControllerBase
{
private readonly AppDbContext _dbContext;
private readonly ILogger<AppController> _logger;
private readonly IRepositoryService _repositoryService;
private readonly JwtTokenService _jwtTokenService;
public AppController(AppDbContext dbContext, ILogger<AppController> logger, IRepositoryService repositoryService, JwtTokenService jwtTokenService)
{
_dbContext = dbContext;
_logger = logger;
_repositoryService = repositoryService;
_jwtTokenService = jwtTokenService;
}
// 이 키값의 제한 시간은 24h이다
[HttpGet]
[CustomOperation("헤더 정보 생성", "헤더에 접근하기 위한 키 값 받아오기", "시스템")]
public async Task<IActionResult> GetHeaderValue(string type, string specific, string project)
{
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;
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>(apiHeader))
{
string msg = "정상 - 로그 저장 실패";
var logProject = new LogProject
{
create_date = DateTime.Now ,
log = $"[{summary}] : 해당 키 유효시간 만료로 인한 새 키 부여"
};
if (await _repositoryService.SaveData<LogProject>(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<APIHeader>(newHeader))
{
string msg = "정상 - 로그 저장 실패";
var logProject = new LogProject
{
create_date = DateTime.Now ,
log = $"[{summary}] : 새로운 등록으로 인한 새 키 부여"
};
// 이거 로그 저장 안되는거 확인!
_logger.LogInformation($"[{summary}] : {logProject.log}");
if (await _repositoryService.SaveData<LogProject>(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();
}
}
[HttpGet("version")]
[CustomOperation("앱 버전 확인","앱 버전을 확인해서 업데이트 여부 판단", "시스템")]
public async Task<IActionResult> 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<Version>
{
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());
}
}
[HttpGet("auth")]
[CustomOperation("서버 접근 권한 확인", "서버 기능을 사용하기 위한 접근에 대해 권한 확인", "시스템")]
public async Task<IActionResult> 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<IActionResult> RetryAccessToken(string refresh)
{
string summary = String.Empty;
try
{
summary = _repositoryService.ReadSummary(typeof(AppController), "AuthProgram");
var refreshToken = await _dbContext.RefreshTokens
.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));
}
}
}