package com.gcsc.guide.auth; import com.gcsc.guide.dto.AuthResponse; import com.gcsc.guide.dto.GoogleLoginRequest; import com.gcsc.guide.dto.UserResponse; import com.gcsc.guide.entity.User; import com.gcsc.guide.repository.UserRepository; import com.gcsc.guide.service.ActivityService; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; @Slf4j @RestController @RequestMapping("/api/auth") @RequiredArgsConstructor public class AuthController { private static final String AUTO_ADMIN_EMAIL = "htlee@gcsc.co.kr"; private final GoogleTokenVerifier googleTokenVerifier; private final JwtTokenProvider jwtTokenProvider; private final UserRepository userRepository; private final ActivityService activityService; /** * Google ID Token으로 로그인/회원가입 처리 후 JWT 발급 */ @PostMapping("/google") public ResponseEntity googleLogin( @Valid @RequestBody GoogleLoginRequest request, HttpServletRequest httpRequest) { GoogleIdToken.Payload payload = googleTokenVerifier.verify(request.idToken()); if (payload == null) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "유효하지 않은 Google 토큰입니다"); } String email = payload.getEmail(); String name = (String) payload.get("name"); String avatarUrl = (String) payload.get("picture"); userRepository.findByEmail(email) .ifPresentOrElse( existingUser -> { existingUser.updateProfile(name, avatarUrl); existingUser.updateLastLogin(); userRepository.save(existingUser); }, () -> createNewUser(email, name, avatarUrl) ); User userWithRoles = userRepository.findByEmailWithRoles(email) .orElseThrow(); activityService.recordLogin( userWithRoles.getId(), httpRequest.getRemoteAddr(), httpRequest.getHeader("User-Agent")); String token = jwtTokenProvider.generateToken( userWithRoles.getId(), userWithRoles.getEmail(), userWithRoles.isAdmin()); return ResponseEntity.ok(new AuthResponse(token, UserResponse.from(userWithRoles))); } /** * 현재 인증된 사용자 정보 조회 */ @GetMapping("/me") public ResponseEntity getCurrentUser(Authentication authentication) { Long userId = (Long) authentication.getPrincipal(); User user = userRepository.findByIdWithRoles(userId) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자를 찾을 수 없습니다")); return ResponseEntity.ok(UserResponse.from(user)); } /** * 로그아웃 (Stateless JWT이므로 서버 측 처리 없음, 프론트에서 토큰 삭제) */ @PostMapping("/logout") public ResponseEntity logout() { return ResponseEntity.noContent().build(); } private User createNewUser(String email, String name, String avatarUrl) { User newUser = new User(email, name, avatarUrl); if (AUTO_ADMIN_EMAIL.equals(email)) { newUser.activate(); newUser.grantAdmin(); log.info("관리자 자동 승인: {}", email); } newUser.updateLastLogin(); return userRepository.save(newUser); } }