From 19fb34bc32bc48d886a81c99974de3b515c0cefc Mon Sep 17 00:00:00 2001 From: Seonkyu_Kim Date: Tue, 11 Mar 2025 11:14:51 +0900 Subject: [PATCH] =?UTF-8?q?[=E2=99=BB=EF=B8=8F]=20USER=20API=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A0=90=EA=B2=80=20=EB=B0=8F=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Program/Common/Data/AppDbContext.cs | 1 + Program/Common/Model/Status.cs | 82 +---- Program/V1/Controllers/UserController.cs | 393 +++++++++++++---------- Program/V1/Models/Log.cs | 12 + 4 files changed, 251 insertions(+), 237 deletions(-) diff --git a/Program/Common/Data/AppDbContext.cs b/Program/Common/Data/AppDbContext.cs index 01efaa5..dd2a32a 100644 --- a/Program/Common/Data/AppDbContext.cs +++ b/Program/Common/Data/AppDbContext.cs @@ -34,6 +34,7 @@ public class AppDbContext: DbContext //MARK: LOG public DbSet LogPush { get; set; } + public DbSet LogUser { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { diff --git a/Program/Common/Model/Status.cs b/Program/Common/Model/Status.cs index 6259732..25b8a3e 100644 --- a/Program/Common/Model/Status.cs +++ b/Program/Common/Model/Status.cs @@ -42,81 +42,23 @@ public static class APIResponse return Send("000", "정상", ""); } - public static APIResponseStatus InvalidInputError() + public static APIResponseStatus InvalidInputError(string? msg = null) { - return Send("100", "입력 값이 유효하지 않습니다.", ""); + return Send("100", msg ?? "입력 값이 유효하지 않습니다.", ""); } - public static APIResponseStatus NotFoundError() + public static APIResponseStatus NotFoundError(string? msg = null) { - return Send("200", "알맞은 값을 찾을 수 없습니다.", ""); + return Send("200", msg ?? "알맞은 값을 찾을 수 없습니다.", ""); + } + + public static APIResponseStatus InternalSeverError(string? msg = null) + { + return Send("300", msg ?? "통신에 오류가 발생하였습니다.", ""); } - public static APIResponseStatus InternalSeverError() + public static APIResponseStatus UnknownError(string? msg = null) { - return Send("300", "통신에 오류가 발생하였습니다.", ""); + return Send("999", msg ?? "알 수 없는 오류가 발생하였습니다.", ""); } - - public static APIResponseStatus UnknownError() - { - return Send("999", "알 수 없는 오류가 발생하였습니다.", ""); - } -} -// -// public static class DefaultResponse -// { -// // private static readonly Lazy _instance = new Lazy(); -// // public static ErrorResponse Instace => _instance.Value; -// -// // private ErrorResponse() -// // { -// // // 외부 초기화 방지 -// // } -// -// -// public static APIResponseStatus Success = new APIResponseStatus -// { -// status = new Status() -// { -// code = "000", -// message = "정상" -// } -// }; -// -// public static APIResponseStatus InvalidInputError = new APIResponseStatus -// { -// status = new Status() -// { -// code = "001", -// message = "입력 값이 유효하지 않습니다." -// } -// }; -// -// public static APIResponseStatus NotFoundError = new APIResponseStatus -// { -// status = new Status() -// { -// code = "002", -// message = "알맞은 값을 찾을 수 없습니다." -// } -// }; -// -// public static APIResponseStatus InternalSeverError = new APIResponseStatus -// { -// status = new Status -// { -// code = "003", -// message = "통신에 오류가 발생하였습니다." -// } -// }; -// -// -// public static APIResponseStatus UnknownError = new APIResponseStatus -// { -// status = new Status() -// { -// code = "999", -// message = "알 수 없는 오류가 발생하였습니다." -// } -// }; -// } +} \ No newline at end of file diff --git a/Program/V1/Controllers/UserController.cs b/Program/V1/Controllers/UserController.cs index eba1297..4bb3a0a 100644 --- a/Program/V1/Controllers/UserController.cs +++ b/Program/V1/Controllers/UserController.cs @@ -18,6 +18,9 @@ using AcaMate.V1.Services; namespace AcaMate.V1.Controllers; +/// +/// USER는 사용자가 자신의 데이터를 보거나 만들거나 하는 등 직접 사용하는 경우에 사용 +/// [ApiController] [Route("/api/v1/in/user")] [ApiExplorerSettings(GroupName = "사용자")] @@ -37,16 +40,17 @@ public class UserController : ControllerBase } [HttpGet] - [CustomOperation("회원 정보 조회", "회원 정보 조회", "사용자")] + [CustomOperation("회원 정보 조회", "회원 정보 조회 (자기자신)", "사용자")] public async Task GetUserData(string token, string refresh) { - if(string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) - return BadRequest(APIResponse.InvalidInputError()); - - + if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) return BadRequest(APIResponse.InvalidInputError()); + if(!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); + string summary = String.Empty; + try { var validateToken = await _repositoryService.ValidateToken(token, refresh); + summary = _repositoryService.ReadSummary(typeof(PushController), "GetUserData"); var user = await _dbContext.User .Where(u => u.uid == validateToken.uid) @@ -61,244 +65,299 @@ public class UserController : ControllerBase type = u.type }) .FirstOrDefaultAsync(); - - // _logger.LogInformation($"CHECK!! {user.}"); - return Ok(APIResponse.Send("000", "정상", user)); + return Ok(APIResponse.Send("000", $"[{summary}], 정상", user)); } catch (TokenException tokenEx) { - _logger.LogInformation($"[로그인] : {tokenEx}"); - return Ok(APIResponse.Send("001", "로그인 진행: 토큰에 문제가 있음",Empty)); + _logger.LogInformation($"[{summary}] : {tokenEx}"); + return Ok(APIResponse.Send("001", $"[{summary}], 토큰에 문제가 있음",Empty)); } catch (RefreshRevokeException refreshEx) { - _logger.LogInformation($"[로그인] : {refreshEx}"); - return Ok(APIResponse.Send("001", "로그인 진행: 리프레시 토큰 폐기",Empty)); + _logger.LogInformation($"[{summary}] : {refreshEx}"); + return Ok(APIResponse.Send("001", $"[{summary}], 폐기된 리프레시 토큰",Empty)); } catch (Exception ex) { - return StatusCode(500, APIResponse.UnknownError()); + return StatusCode(500, APIResponse.UnknownError(ex.Message)); } } + [HttpGet("academy")] + [CustomOperation("학원 리스트 확인", "사용자가 등록된 학원 리스트 확인", "사용자")] + public async Task ReadAcademyInfo(string token, string refresh) + { + if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) return BadRequest(APIResponse.InvalidInputError()); + if(!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); + string summary = String.Empty; + + try + { + var validateToken = await _repositoryService.ValidateToken(token, refresh); + summary = _repositoryService.ReadSummary(typeof(PushController), "ReadAcademyInfo"); + + var academies = await (from ua in _dbContext.UserAcademy + join a in _dbContext.Academy on ua.bid equals a.bid + where ua.uid == validateToken.uid + select new AcademyName + { + bid = a.bid, + name = a.business_name + }).ToListAsync(); + + + return Ok(APIResponse.Send("000",$"[{summary}], 정상.",academies)); + } + catch (TokenException tokenEx) + { + _logger.LogInformation($"[{summary}] : {tokenEx}"); + return Ok(APIResponse.Send("001", $"[{summary}], 토큰에 문제가 있음",Empty)); + } + catch (RefreshRevokeException refreshEx) + { + _logger.LogInformation($"[{summary}] : {refreshEx}"); + return Ok(APIResponse.Send("001", $"[{summary}], 폐기된 리프레시 토큰",Empty)); + } + catch (Exception ex) + { + _logger.LogInformation($"[{summary}] : {ex}"); + return StatusCode(500, APIResponse.UnknownError(ex.Message)); + } + } + [HttpGet("login")] [CustomOperation("SNS 로그인", "로그인 후 회원이 있는지 확인", "사용자")] public async Task Login(string acctype, string sns_id) { // API 동작 파라미터 입력 값 확인 - if (string.IsNullOrEmpty(acctype) && string.IsNullOrEmpty(sns_id)) - return BadRequest(APIResponse.InvalidInputError()); - + if (string.IsNullOrEmpty(acctype) && string.IsNullOrEmpty(sns_id)) return BadRequest(APIResponse.InvalidInputError()); + if(!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); + string summary = String.Empty; + try { + summary = _repositoryService.ReadSummary(typeof(PushController), "Login"); + var login = await _dbContext.Login .FirstOrDefaultAsync(l => l.sns_type == acctype && l.sns_id == sns_id); if (login != null) { // 로그인 정보가 존재 하는 상황 - var uid = login.uid; - var user = await _dbContext.User - .FirstOrDefaultAsync(u => u.uid == uid); + .FirstOrDefaultAsync(u => u.uid == login.uid); - if (user != null) + // 회원 정보 없음 + if (user == null) return Ok(APIResponse.Send("002", $"[{summary}], 회원 정보 오류",Empty)); + + // 정상적으로 User 테이블에도 있는것이 확인 됨 + user.login_date = DateTime.Now; + await _dbContext.SaveChangesAsync(); + + // 토큰 생성은 로그인이 이제 되고 나서 한다. + var accessToken = _jwtTokenService.GenerateJwtToken(login.uid); + var refreshToken = _jwtTokenService.GenerateRefreshToken(login.uid); + _logger.LogInformation($"[{summary}] : {login.uid} = {accessToken}, {refreshToken}"); + + if (await _repositoryService.SaveData(refreshToken)) { - // 정상적으로 User 테이블에도 있는것이 확인 됨 - user.login_date = DateTime.Now; - await _dbContext.SaveChangesAsync(); - - // 토큰 생성은 로그인이 이제 되고 나서 한다. - var accessToken = _jwtTokenService.GenerateJwtToken(uid);//, "Normal"); - var refreshToken = _jwtTokenService.GenerateRefreshToken(uid); - _logger.LogInformation($"{uid}: {accessToken}, {refreshToken}"); - - // await _repositoryService.SaveData(refreshToken, rt => rt.uid); - await _repositoryService.SaveData(refreshToken); - - return Ok(APIResponse.Send("000","정상", new + var logUser = new LogUser { - token = accessToken, - refresh = refreshToken.refresh_token - })); + uid = login.uid, + create_date = DateTime.Now, + create_uid = "System", + log = $"[{summary}] : 정상" + }; + await _repositoryService.SaveData(logUser); + return Ok(APIResponse.Send("000",$"[{summary}], 정상", + new { token = accessToken, refresh = refreshToken.refresh_token })); } - } - // case 1: Login 테이블에 값이 없다 == 로그인이 처음 - // case 2: User 테이블에 값이 없다 == 이건 문제가 있는 상황 -> 해결은 회원가입 재 진행 시도 - // Login에는 있는데 User 테이블에 없다? 말이 안되긴 하는데... - - return Ok(APIResponse.Send("001", "회원가입 진행: 로그인 정보가 없음",Empty)); - } - catch (Exception ex) - { - _logger.LogInformation($"[로그인][에러] : {ex}"); - return StatusCode(500, APIResponse.UnknownError()); - } - } - - [HttpGet("academy")] - [CustomOperation("학원 리스트 확인", "사용자가 등록된 학원 리스트 확인", "사용자")] - public async Task ReadAcademyInfo(string token, string refresh) - { - _logger.LogInformation($"토큰 : {token}, {refresh}"); - - if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) - { - return BadRequest(APIResponse.InvalidInputError()); - } - - try - { - var validateToken = await _repositoryService.ValidateToken(token, refresh); - var uid = validateToken.uid; - - var userAcademy = await _dbContext.UserAcademy - .Where(ua => ua.uid == uid) - .Select(ua => ua.bid) - .ToListAsync(); - - - var academies = await _dbContext.Academy - .Where(a => userAcademy.Contains(a.bid)) - .Select(a => new AcademyName + else { - bid = a.bid, - name = a.business_name - }) - .ToListAsync(); + var logUser = new LogUser + { + uid = login.uid, + create_date = DateTime.Now, + create_uid = "System", + log = $"[{summary}] : 실패" + }; + await _repositoryService.SaveData(logUser); + + return Ok(APIResponse.InternalSeverError($"[{summary}], 로그인 저장 실패")); + } + + } - return Ok(APIResponse.Send("000","정상.",academies)); - } - catch (TokenException tokenEx) - { - _logger.LogInformation($"[로그인] : {tokenEx}"); - return Ok(APIResponse.Send("001", "[로그인] : 토큰에 문제가 있음",Empty)); - } - catch (RefreshRevokeException refreshEx) - { - _logger.LogInformation($"[로그인] : {refreshEx}"); - return Ok(APIResponse.Send("001", "[로그인] : 폐기된 리프레시 토큰",Empty)); + return Ok(APIResponse.Send("001", $"[{summary}], 로그인 정보 없음",Empty)); } catch (Exception ex) { - _logger.LogInformation($"[로그인][에러] : {ex}"); - return StatusCode(500, APIResponse.UnknownError()); + _logger.LogInformation($"[{summary}] : {ex}"); + return StatusCode(500, APIResponse.UnknownError(ex.Message)); } - } - + [HttpPost("register")] [CustomOperation("회원 가입", "사용자 회원 가입", "사용자")] public async Task UserRegister([FromBody] UserAll request) { - if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); - - var atIndex = request.email.IndexOf('@'); - var localPartEmail = request.email.Substring(0, atIndex); - var uid = $"AM{localPartEmail}{DateTime.Now:yyyyMMdd}"; - - var user = new User - { - uid = uid, - name = request.name, - birth = request.birth, - type = request.type, - device_id = request.device_id, - auto_login_yn = request.auto_login_yn, - login_date = request.login_date, - push_token = request.push_token - }; - var login = new Login - { - uid = uid, - sns_id = request.sns_id, - sns_type = request.sns_type - }; + if(!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); + string summary = String.Empty; - var permission = new Permission + try { - uid = uid, - location_yn = request.location_yn, - camera_yn = request.camera_yn, - photo_yn = request.photo_yn, - push_yn = request.push_yn, - market_app_yn = request.market_app_yn, - market_sms_yn = request.market_sms_yn, - market_email_yn = request.market_email_yn - }; + summary = _repositoryService.ReadSummary(typeof(PushController), "UserRegister"); + var localPartEmail = request.email.Substring(0, request.email.IndexOf('@')); + var uid = $"AM{localPartEmail}{DateTime.Now:yyyyMMdd}"; + + var user = new User + { + uid = uid, + name = request.name, + birth = request.birth, + type = request.type, + device_id = request.device_id, + auto_login_yn = request.auto_login_yn, + login_date = request.login_date, + push_token = request.push_token + }; + var login = new Login + { + uid = uid, + sns_id = request.sns_id, + sns_type = request.sns_type + }; - var contact = new Contact - { - uid = uid, - email = request.email, - phone = request.phone, - address = request.address - }; + var permission = new Permission + { + uid = uid, + location_yn = request.location_yn, + camera_yn = request.camera_yn, + photo_yn = request.photo_yn, + push_yn = request.push_yn, + market_app_yn = request.market_app_yn, + market_sms_yn = request.market_sms_yn, + market_email_yn = request.market_email_yn + }; - - if (await _repositoryService.SaveData(user)) - { - await _repositoryService.SaveData(login); - await _repositoryService.SaveData(permission); - await _repositoryService.SaveData(contact); + var contact = new Contact + { + uid = uid, + email = request.email, + phone = request.phone, + address = request.address + }; + + var logUser = new LogUser + { + uid = login.uid, + create_date = DateTime.Now, + create_uid = "System", + log = "" + }; + + var saveUser = await _repositoryService.SaveData(user); + var saveLogin = await _repositoryService.SaveData(login); + var savePermission = await _repositoryService.SaveData(permission); + var saveContact = await _repositoryService.SaveData(contact); + if (saveUser && saveLogin && savePermission && saveContact) + { + + var token = _jwtTokenService.GenerateJwtToken(uid); + var refreshToken = _jwtTokenService.GenerateRefreshToken(uid); + + if (await _repositoryService.SaveData(refreshToken)) + { + logUser.log = $"[{summary}] : 정상"; + + if (await _repositoryService.SaveData(logUser)) + _logger.LogError($"[{summary}] : 로그 저장 성공"); + + return Ok(APIResponse.Send("000",$"[{summary}], 정상",new + { + accessToken = token, + refreshToken = refreshToken.refresh_token + })); + } + else + { + _logger.LogError($"[{summary}] : 토큰 저장 실패"); + } + } + + logUser.log = $"[{summary}] : 동작 실패"; + await _repositoryService.SaveData(logUser); + + return Ok(APIResponse.InternalSeverError()); } - - // TO-DO: jwt 토큰 만들어서 여기서 보내는 작업을 해야 함 - var token = _jwtTokenService.GenerateJwtToken(uid); - var refreshToken = _jwtTokenService.GenerateRefreshToken(uid); - - await _repositoryService.SaveData(refreshToken); - - return Ok(APIResponse.Send("000","정상",new + catch (Exception ex) { - accessToken = token, - refreshToken = refreshToken.refresh_token - })); + _logger.LogInformation($"[{summary}] : {ex.Message}"); + return BadRequest(APIResponse.UnknownError(ex.Message)); + } + } [HttpGet("logout")] [CustomOperation("로그아웃", "사용자 로그아웃", "사용자")] - public async Task Logout(string token, string refresh) //([FromBody] UserAll request) + public async Task Logout(string token, string refresh) { if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) return BadRequest(APIResponse.InvalidInputError()); - + if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); + string summary = String.Empty; + try { + summary = _repositoryService.ReadSummary(typeof(PushController), "UserRegister"); + + // 여기서 애초에 토큰 관련 에러가 2개가 나오게 만들어져 있음 var validateToken = await _repositoryService.ValidateToken(token, refresh); + var refreshToken = await _dbContext.RefreshTokens.FirstOrDefaultAsync(r => r.uid == validateToken.uid); + if (refreshToken != null) { refreshToken.revoke_Date = DateTime.Now; await _repositoryService.SaveData(refreshToken); - return Ok(APIResponse.Send("000", "로그아웃 정상", Empty)); - } - else - { - return Ok(APIResponse.Send("000", "로그아웃 정상", Empty)); + return Ok(APIResponse.Send("000", $"[{summary}], 로그아웃 정상", Empty)); } + // 리프레시 토큰이 없다?? 그럼 이거 무조건 문제지 (이유를 알 수 없는) + return Ok(APIResponse.UnknownError()); } catch (TokenException tokenEx) { - return Ok(APIResponse.Send("101", "입력 받은 토큰의 문제", Empty)); + return Ok(APIResponse.Send("101", $"[{summary}], 입력 받은 토큰의 문제", Empty)); } catch (RefreshRevokeException refreshEx) { - return Ok(APIResponse.Send("102", "폐기된 리프레시 토큰", Empty)); + return Ok(APIResponse.Send("102", $"[{summary}], 폐기된 리프레시 토큰", Empty)); } catch (Exception ex) { - return StatusCode(500, APIResponse.UnknownError()); + return StatusCode(500, APIResponse.UnknownError($"[{summary}], {ex.Message}")); } } // [HttpGet("set")] - - - - +} - -} \ No newline at end of file +/* + string uid = ""; + if (token == "System") uid = "System"; + else { + if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) return BadRequest(APIResponse.InvalidInputError()); + if(!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError()); + + var validateToken = await _repositoryService.ValidateToken(token, refresh); + uid = validateToken.uid; + } + + string summary = String.Empty; + try + { + summary = _repositoryService.ReadSummary(typeof(PushController), "GetUserData"); + } +*/ \ No newline at end of file diff --git a/Program/V1/Models/Log.cs b/Program/V1/Models/Log.cs index ca2b213..d342fb9 100644 --- a/Program/V1/Models/Log.cs +++ b/Program/V1/Models/Log.cs @@ -16,4 +16,16 @@ public class LogPush public DateTime create_date {get; set;} public string create_uid {get; set;} public string log { get; set; } +} + +[Table("log_user")] +public class LogUser +{ + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int lid { get; set; } + public string uid {get; set;} + public DateTime create_date {get; set;} + public string create_uid {get; set;} + public string log { get; set; } } \ No newline at end of file