97 lines
3.4 KiB
Java
97 lines
3.4 KiB
Java
|
|
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.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
|
||
|
|
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;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Google ID Token으로 로그인/회원가입 처리 후 JWT 발급
|
||
|
|
*/
|
||
|
|
@PostMapping("/google")
|
||
|
|
public ResponseEntity<AuthResponse> googleLogin(@Valid @RequestBody GoogleLoginRequest request) {
|
||
|
|
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();
|
||
|
|
|
||
|
|
String token = jwtTokenProvider.generateToken(
|
||
|
|
userWithRoles.getId(), userWithRoles.getEmail(), userWithRoles.isAdmin());
|
||
|
|
|
||
|
|
return ResponseEntity.ok(new AuthResponse(token, UserResponse.from(userWithRoles)));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 현재 인증된 사용자 정보 조회
|
||
|
|
*/
|
||
|
|
@GetMapping("/me")
|
||
|
|
public ResponseEntity<UserResponse> 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<Void> 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);
|
||
|
|
}
|
||
|
|
}
|