using System.Security.Claims; 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 System.Text.Json; namespace Back.Program.Services.V1 { public class UserService : IUserService { private readonly ILogger _logger; private readonly IUserRepository _userRepository; private readonly JwtTokenService _jwtTokenService; private readonly IRepositoryService _repositoryService; private readonly ILogRepository _logRepository; private readonly ISessionService _sessionService; private readonly IAppService _appService; public UserService(ILogger logger, IUserRepository userRepository, JwtTokenService jwtTokenService, IRepositoryService repositoryService, ILogRepository logRepository, ISessionService sessionService, IAppService appService) { _logger = logger; _userRepository = userRepository; _jwtTokenService = jwtTokenService; _repositoryService = repositoryService; _logRepository = logRepository; _sessionService = sessionService; _appService = appService; } public async Task> GetUser(string summary, string token) { var validToken = await _jwtTokenService.ValidateToken(token); if (validToken == null) return APIResponse.AccessExpireError(); var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; var user = await _userRepository.FindUser(uid); return APIResponse.Send("000", $"[{summary}], 정상", user); // user 없는 경우가 없네? 그거도 만들것 } public async Task> Login(string summary, string accType, string snsId) { var login = await _userRepository.FindLogin(accType, snsId); if (login == null) return APIResponse.Send("001", $"[{summary}], 로그인 정보 없음", new { }); var user = await _userRepository.FindUser(login.uid); if (user == null) return APIResponse.Send("002", $"[{summary}], 회원 정보 오류", new {}); user.login_date = DateTime.Now; var token = _jwtTokenService.GenerateJwtToken(user.uid); var refresh = _jwtTokenService.GenerateRefreshToken(user.uid); if (await _repositoryService.SaveData(refresh)) { return APIResponse.Send("000", $"[{summary}], 정상", new { token = token, refresh = refresh.refresh_token }); } // 토큰 저장에 실패 및 로그인도 실패 return APIResponse.InternalSeverError($"[{summary}], 로그인 동작 실패"); } public async Task> Register(string summary, UserAll request) { 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 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 }; 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 refresh = _jwtTokenService.GenerateRefreshToken(uid); if (await _repositoryService.SaveData(refresh)) { logUser.log = $"[{summary}] : 정상"; if (await _logRepository.SaveLogUser(logUser)) { _logger.LogInformation($"[{summary}]: 성공"); } else { _logger.LogInformation($"[{summary}]: 성공 - 로그 저장 실패"); } return APIResponse.Send("000", $"[{summary}], 정상", new { token = token, refresh = refresh.refresh_token }); } else { logUser.log = $"[{summary}] : 실패"; if (await _logRepository.SaveLogUser(logUser)) { _logger.LogInformation($"[{summary}]: 실패"); } else { _logger.LogInformation($"[{summary}]: 실패 - 로그 저장 실패"); } } } return APIResponse.InternalSeverError($"[{summary}], 회원가입 동작 실패"); } public async Task> Logout(string summary, string token) { var validToken = await _jwtTokenService.ValidateToken(token); if (validToken == null) return APIResponse.AccessExpireError(); var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; var refresh = await _userRepository.FindRefreshToken(uid); if (refresh != null) { refresh.revoke_Date = DateTime.Now; if (await _repositoryService.SaveData(refresh)) { return APIResponse.Send("000", $"[{summary}], 로그아웃 정상", new {}); } } return APIResponse.UnknownError(); } public async Task> Cancel(string summary, string token) { var validToken = await _jwtTokenService.ValidateToken(token); if (validToken == null) return APIResponse.AccessExpireError(); var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; var user = await _userRepository.FindUser(uid); if (user == null) return APIResponse.Send("001", $"[{summary}], 회원 정보 확인 오류", new {}); if (await _repositoryService.DeleteData(user)) { if (await _logRepository.SaveLogUser(new LogUser { uid = user.uid, create_date = DateTime.Now, create_uid = "System", log = $"[{summary}] : 정상" })) { _logger.LogInformation($"[{summary}]: 성공"); } else { _logger.LogInformation($"[{summary}]: 성공 - 로그 저장 실패"); } return APIResponse.Send("000", $"[{summary}], 정상", new {}); } else { if (await _logRepository.SaveLogUser(new LogUser { uid = user.uid, create_date = DateTime.Now, create_uid = "System", log = $"[{summary}] : 실패" })) { _logger.LogInformation($"[{summary}]: 실패"); } else { _logger.LogInformation($"[{summary}]: 실패 - 로그 저장 실패"); } } return APIResponse.InternalSeverError(); } public async Task> GetAcademy(string summary, string token) { var validToken = await _jwtTokenService.ValidateToken(token); if (validToken == null) return APIResponse.AccessExpireError(); var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; var user = await _userRepository.FindUser(uid); if (user == null) return APIResponse.Send("001", $"[{summary}], 회원 정보 확인 오류", new {}); var academyList = await _userRepository.FindAcademies(uid); _logger.LogInformation($"[{summary}]: 성공"); return APIResponse.Send("000", $"[{summary}], 정상.", academyList); } public async Task> GetSessionData(string summary) { try { _logger.LogInformation($"[{summary}] 세션 데이터 조회 시작"); // 1. 세션에서 토큰 가져오기 var (result, token) = await _sessionService.GetString("token"); _logger.LogInformation($"[{summary}] 세션에서 토큰 가져오기 결과: {result}, 토큰: {token}"); if (!result || string.IsNullOrEmpty(token)) { _logger.LogWarning($"[{summary}] 세션에 토큰이 없습니다"); return APIResponse.Send("200", "세션에 토큰이 없습니다", new { name = "" }); } // 2. 토큰 검증 var validToken = await _jwtTokenService.ValidateToken(token); _logger.LogInformation($"[{summary}] 토큰 검증 결과: {validToken != null}"); if (validToken == null) { // 3. 토큰이 유효하지 않으면 리프레시 토큰으로 새 토큰 발급 시도 var (refreshResult, refreshToken) = await _sessionService.GetString("refresh"); _logger.LogInformation($"[{summary}] 리프레시 토큰 가져오기 결과: {refreshResult}, 토큰: {refreshToken}"); if (!refreshResult || string.IsNullOrEmpty(refreshToken)) { _logger.LogWarning($"[{summary}] 리프레시 토큰이 없습니다"); return APIResponse.Send("201", "리프레시 토큰이 없습니다", new { name = "" }); } // 4. 리프레시 토큰으로 새 토큰 발급 var retryResult = await _appService.RetryAccess(summary, refreshToken); _logger.LogInformation($"[{summary}] 토큰 재발급 결과: {retryResult.status.code}"); if (retryResult.status.code == "000") { // 5. 새 토큰을 세션에 저장 var data = JsonSerializer.Deserialize(JsonSerializer.Serialize(retryResult.data)); var newToken = data.GetProperty("access").GetString(); await _sessionService.SetString("token", newToken); _logger.LogInformation($"[{summary}] 새 토큰 세션 저장 완료"); // 6. 새 토큰으로 사용자 정보 조회 validToken = await _jwtTokenService.ValidateToken(newToken); } else { _logger.LogWarning($"[{summary}] 토큰 갱신 실패: {retryResult.status.message}"); return APIResponse.Send("202", "토큰 갱신 실패", new { name = "" }); } } // 7. 최종적으로 유효한 토큰으로 사용자 정보 조회 var uid = validToken.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty; _logger.LogInformation($"[{summary}] 사용자 ID: {uid}"); var user = await _userRepository.FindUser(uid); _logger.LogInformation($"[{summary}] 사용자 정보 조회 결과: {user != null}"); if (user == null) { _logger.LogWarning($"[{summary}] 사용자 정보를 찾을 수 없습니다"); return APIResponse.Send("203", "사용자 정보를 찾을 수 없습니다", new { name = "" }); } _logger.LogInformation($"[{summary}] 세션 데이터 조회 성공: {user.name}"); return APIResponse.Send("000", $"[{summary}], 정상", new { name = user.name }); } catch (Exception ex) { _logger.LogError($"[{summary}] 세션 데이터 조회 중 오류: {ex.Message}"); _logger.LogError($"[{summary}] 스택 트레이스: {ex.StackTrace}"); return APIResponse.InternalSeverError($"[{summary}], 세션 데이터 조회 실패"); } } } }