GoogleOAuthUserLoginOrCreateService.java
package com.hwhub.backend.application.service.oauth;
import com.hwhub.backend.domain.enums.AuthProvider;
import com.hwhub.backend.domain.enums.ProgramType;
import com.hwhub.backend.domain.model.UserModel;
import com.hwhub.backend.domain.oauth.google.GoogleUserInfo;
import com.hwhub.backend.domain.repository.UserRepository;
import com.hwhub.backend.presentation.rest.common.EmailAlreadyUsedForLocalAccountException;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Google OAuth ユーザーに対して、 ログインまたは新規ユーザー作成を行い、JWT を発行するサービス。
*
* <p>責務:
*
* <ul>
* <li>GoogleOAuthUserResolver の判定結果に基づき
* <li>既存ユーザーならログイン
* <li>新規ユーザーなら m_user を作成
* <li>最終的に JwtProvider を使って JWT を発行する
* </ul>
*
* <p>このクラスは:
*
* <ul>
* <li>OAuth の詳細(code / state / token)を知らない
* <li>純粋に「ユーザー認証」という観点に集中する
* </ul>
*
* <p>位置づけ:
*
* <ul>
* <li>認証ドメイン寄りの Application Service
* <li>email/password ログインの Service と思想的に同列
* </ul>
*/
@Service
@RequiredArgsConstructor
public class GoogleOAuthUserLoginOrCreateService {
private final UserRepository userRepository;
private static final long USER_ID_ADMIN = 1L;
@Transactional
public UserModel loginOrCreate(GoogleUserInfo info) {
String sub = info.getSub();
String email = info.getEmail();
String name = info.getName();
// 既にGOOGLE紐付け済みならそれを返す
var existing =
userRepository.findByAuthProviderAndAuthProviderId(AuthProvider.GOOGLE.getCode(), sub);
if (existing.isPresent()) {
return existing.get();
}
// まだ紐付いてない場合
// emailが既に使われているなら、「ログインしてからgoogleアカウントと連携させる
if (email != null && userRepository.countByEmail(email) > 0) {
throw new EmailAlreadyUsedForLocalAccountException("Email already used.");
}
// 新規作成(password_hashはNULL)
LocalDateTime now = LocalDateTime.now();
String displayName = (name == null || name.isBlank()) ? "User" : name;
UserModel model = UserModel.createGoogleUser(email, sub, displayName, now);
return userRepository.insert(model, USER_ID_ADMIN, ProgramType.ONL_AUTH_GOOGLE.getCode());
}
}