-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
336 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...Tags/user/controller/EmailVerification.kt → ...ct/memoWithTags/mail/EmailVerification.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...er/persistence/EmailVerificationEntity.kt → ...il/persistence/EmailVerificationEntity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ersistence/EmailVerificationRepository.kt → ...ersistence/EmailVerificationRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
src/main/kotlin/com/wafflestudio/toyproject/memoWithTags/mail/service/MailService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.wafflestudio.toyproject.memoWithTags.mail.service | ||
|
||
interface MailService { | ||
/** | ||
* 메일을 보내는 함수. | ||
* 개발 환경에서는 로그만 출력하고, 배포 환경에서만 실제 메일을 보내기 위해 인터페이스를 선언함 | ||
*/ | ||
fun sendMail(toEmail: String, title: String, content: String) | ||
} |
2 changes: 1 addition & 1 deletion
2
...oWithTags/user/service/NoOpMailService.kt → ...oWithTags/mail/service/NoOpMailService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...oWithTags/user/service/SmtpMailService.kt → ...oWithTags/mail/service/SmtpMailService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
...otlin/com/wafflestudio/toyproject/memoWithTags/social/controller/SocialLoginController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.wafflestudio.toyproject.memoWithTags.social.controller | ||
|
||
import com.wafflestudio.toyproject.memoWithTags.exception.OAuthRequestException | ||
import com.wafflestudio.toyproject.memoWithTags.social.service.SocialLoginService | ||
import com.wafflestudio.toyproject.memoWithTags.user.SocialType | ||
import com.wafflestudio.toyproject.memoWithTags.user.dto.UserResponse.LoginResponse | ||
import io.swagger.v3.oas.annotations.Operation | ||
import org.springframework.http.HttpStatus | ||
import org.springframework.http.ResponseEntity | ||
import org.springframework.web.bind.annotation.GetMapping | ||
import org.springframework.web.bind.annotation.PathVariable | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RequestParam | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
@RequestMapping("/api/v1") | ||
class SocialLoginController( | ||
private val socialLoginService: SocialLoginService | ||
) { | ||
@Operation(summary = "소셜 로그인 요청") | ||
@GetMapping("/auth/code/{provider}") | ||
fun oauthCallback( | ||
@RequestParam(value = "code", required = false) code: String?, | ||
@PathVariable provider: String | ||
): ResponseEntity<Unit> { | ||
if (code == null) throw OAuthRequestException() | ||
val appLink = "memowithtags://oauth/$provider?code=$code" | ||
return ResponseEntity.status(HttpStatus.FOUND) | ||
.header("Location", appLink) | ||
.build() | ||
} | ||
|
||
@Operation(summary = "소셜 로그인 처리") | ||
@GetMapping("/auth/login/{provider}") | ||
fun oauthLogin( | ||
@RequestParam(value = "code") code: String, | ||
@PathVariable provider: String | ||
): ResponseEntity<LoginResponse> { | ||
val socialType = SocialType.from(provider) | ||
val loginResult = when (socialType) { | ||
SocialType.KAKAO -> socialLoginService.kakaoLogin(code) | ||
SocialType.NAVER -> socialLoginService.naverLogin(code) | ||
SocialType.GOOGLE -> socialLoginService.googleLogin(code) | ||
else -> throw OAuthRequestException() | ||
} | ||
return ResponseEntity.ok(LoginResponse(loginResult.second, loginResult.third)) | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...oject/memoWithTags/user/dto/GoogleUser.kt → ...ect/memoWithTags/social/dto/GoogleUser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...roject/memoWithTags/user/dto/KakaoUser.kt → ...ject/memoWithTags/social/dto/KakaoUser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...roject/memoWithTags/user/dto/NaverUser.kt → ...ject/memoWithTags/social/dto/NaverUser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
...main/kotlin/com/wafflestudio/toyproject/memoWithTags/social/service/SocialLoginService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package com.wafflestudio.toyproject.memoWithTags.social.service | ||
|
||
import com.wafflestudio.toyproject.memoWithTags.exception.EmailAlreadyExistsException | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.GoogleOAuthToken | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.GoogleProfile | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.KakaoOAuthToken | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.KakaoProfile | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.NaverOAuthToken | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.NaverProfile | ||
import com.wafflestudio.toyproject.memoWithTags.user.GoogleUtil | ||
import com.wafflestudio.toyproject.memoWithTags.user.JwtUtil | ||
import com.wafflestudio.toyproject.memoWithTags.user.KakaoUtil | ||
import com.wafflestudio.toyproject.memoWithTags.user.NaverUtil | ||
import com.wafflestudio.toyproject.memoWithTags.user.SocialType | ||
import com.wafflestudio.toyproject.memoWithTags.user.controller.User | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class SocialLoginService( | ||
private val socialUserService: SocialUserService, | ||
private val kakaoUtil: KakaoUtil, | ||
private val naverUtil: NaverUtil, | ||
private val googleUtil: GoogleUtil | ||
) { | ||
private val logger = LoggerFactory.getLogger(javaClass) | ||
|
||
/** | ||
* 네이버 프로필 정보를 받아온 후, 로그인 또는 회원가입 후 로그인 로직을 처리하는 함수 | ||
*/ | ||
fun naverLogin(accessCode: String): Triple<User, String, String> { | ||
val oAuthToken: NaverOAuthToken = naverUtil.requestToken(accessCode) | ||
val naverProfile: NaverProfile = naverUtil.requestProfile(oAuthToken) | ||
|
||
val naverEmail = naverProfile.email | ||
val userEntity = socialUserService.findUserByEmail(naverEmail) | ||
|
||
// 기존에 등록된 이메일이 있으면서 다른 서비스로 로그인을 한 경우 예외 발생 | ||
val user: User = if (userEntity != null && userEntity.socialType == SocialType.NAVER) { | ||
logger.info("naver user already exists: ${userEntity.id}, ${userEntity.email}") | ||
User.fromEntity(userEntity) | ||
} else if (userEntity == null) { | ||
logger.info("creating naver user $naverEmail") | ||
socialUserService.createNaverUser(naverProfile) | ||
} else { | ||
throw EmailAlreadyExistsException() | ||
} | ||
|
||
return Triple( | ||
user, | ||
JwtUtil.generateAccessToken(naverEmail), | ||
JwtUtil.generateRefreshToken(naverEmail) | ||
) | ||
} | ||
|
||
/** | ||
* 카카오 프로필 정보를 받아온 후, 로그인 또는 회원가입 후 로그인 로직을 처리하는 함수 | ||
*/ | ||
fun kakaoLogin(accessCode: String): Triple<User, String, String> { | ||
val oAuthToken: KakaoOAuthToken = kakaoUtil.requestToken(accessCode) | ||
val kakaoProfile: KakaoProfile = kakaoUtil.requestProfile(oAuthToken) | ||
|
||
val kakaoEmail = kakaoProfile.kakao_account.email | ||
val userEntity = socialUserService.findUserByEmail(kakaoEmail) | ||
|
||
// 기존에 등록된 이메일이 있으면서 다른 서비스로 로그인을 한 경우 예외 발생 | ||
val user: User = if (userEntity != null && userEntity.socialType == SocialType.KAKAO) { | ||
logger.info("kakao user already exists: ${userEntity.id}, ${userEntity.email}") | ||
User.fromEntity(userEntity) | ||
} else if (userEntity == null) { | ||
logger.info("creating kakao user $kakaoEmail") | ||
socialUserService.createKakaoUser(kakaoProfile) | ||
} else { | ||
throw EmailAlreadyExistsException() | ||
} | ||
|
||
return Triple( | ||
user, | ||
JwtUtil.generateAccessToken(kakaoEmail), | ||
JwtUtil.generateRefreshToken(kakaoEmail) | ||
) | ||
} | ||
|
||
/** | ||
* 구글 프로필 정보를 받아온 후, 로그인 또는 회원가입 후 로그인 로직을 처리하는 함수 | ||
*/ | ||
fun googleLogin(accessCode: String): Triple<User, String, String> { | ||
val oAuthToken: GoogleOAuthToken = googleUtil.requestToken(accessCode) | ||
val googleProfile: GoogleProfile = googleUtil.requestProfile(oAuthToken) | ||
|
||
val googleEmail = googleProfile.email | ||
val userEntity = socialUserService.findUserByEmail(googleEmail) | ||
|
||
// 기존에 등록된 이메일이 있으면서 다른 서비스로 로그인을 한 경우 예외 발생 | ||
val user: User = if (userEntity != null && userEntity.socialType == SocialType.GOOGLE) { | ||
logger.info("google user already exists: ${userEntity.id}, ${userEntity.email}") | ||
User.fromEntity(userEntity) | ||
} else if (userEntity == null) { | ||
logger.info("creating google user $googleEmail") | ||
socialUserService.createGoogleUser(googleProfile) | ||
} else { | ||
throw EmailAlreadyExistsException() | ||
} | ||
|
||
return Triple( | ||
user, | ||
JwtUtil.generateAccessToken(googleEmail), | ||
JwtUtil.generateRefreshToken(googleEmail) | ||
) | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
src/main/kotlin/com/wafflestudio/toyproject/memoWithTags/social/service/SocialUserService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package com.wafflestudio.toyproject.memoWithTags.social.service | ||
|
||
import com.wafflestudio.toyproject.memoWithTags.social.dto.GoogleProfile | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.KakaoProfile | ||
import com.wafflestudio.toyproject.memoWithTags.social.dto.NaverProfile | ||
import com.wafflestudio.toyproject.memoWithTags.user.SocialType | ||
import com.wafflestudio.toyproject.memoWithTags.user.controller.User | ||
import com.wafflestudio.toyproject.memoWithTags.user.persistence.UserEntity | ||
import com.wafflestudio.toyproject.memoWithTags.user.persistence.UserRepository | ||
import org.springframework.stereotype.Service | ||
import org.springframework.transaction.annotation.Transactional | ||
import java.time.Instant | ||
|
||
@Service | ||
class SocialUserService( | ||
private val userRepository: UserRepository | ||
) { | ||
/** | ||
* 네이버 로그인 시 저장되어 있는 User 정보가 없을 경우, DB에 User를 생성하는 함수 | ||
*/ | ||
@Transactional | ||
fun createNaverUser(naverProfile: NaverProfile): User { | ||
val naverEmail = naverProfile.email | ||
val naverNickname = naverProfile.nickname | ||
val encryptedPassword = "naver_registered_user" | ||
|
||
val userEntity = userRepository.save( | ||
UserEntity( | ||
email = naverEmail, | ||
nickname = naverNickname, | ||
hashedPassword = encryptedPassword, | ||
verified = true, | ||
socialType = SocialType.NAVER, | ||
createdAt = Instant.now() | ||
) | ||
) | ||
|
||
return User.fromEntity(userEntity) | ||
} | ||
|
||
/** | ||
* 카카오 로그인 시 저장되어 있는 User 정보가 없을 경우, DB에 User를 생성하는 함수 | ||
*/ | ||
@Transactional | ||
fun createKakaoUser(kakaoProfile: KakaoProfile): User { | ||
val kakaoEmail = kakaoProfile.kakao_account.email | ||
val kakaoNickname = kakaoProfile.kakao_account.profile.nickname | ||
val encryptedPassword = "kakao_registered_user" | ||
|
||
val userEntity = userRepository.save( | ||
UserEntity( | ||
email = kakaoEmail, | ||
nickname = kakaoNickname, | ||
hashedPassword = encryptedPassword, | ||
verified = true, | ||
socialType = SocialType.KAKAO, | ||
createdAt = Instant.now() | ||
) | ||
) | ||
|
||
return User.fromEntity(userEntity) | ||
} | ||
|
||
/** | ||
* 구글 로그인 시 저장되어 있는 User 정보가 없을 경우, DB에 User를 생성하는 함수 | ||
*/ | ||
@Transactional | ||
fun createGoogleUser(profile: GoogleProfile): User { | ||
val googleEmail = profile.email | ||
val googleNickname = profile.name | ||
val encryptedPassword = "google_registered_user" | ||
|
||
val userEntity = userRepository.save( | ||
UserEntity( | ||
email = googleEmail, | ||
nickname = googleNickname, | ||
hashedPassword = encryptedPassword, | ||
verified = true, | ||
socialType = SocialType.GOOGLE, | ||
createdAt = Instant.now() | ||
) | ||
) | ||
|
||
return User.fromEntity(userEntity) | ||
} | ||
|
||
/** | ||
* 해당 메일의 User를 찾는 함수. 없으면 null을 반환한다. | ||
*/ | ||
@Transactional | ||
fun findUserByEmail(email: String): UserEntity? { | ||
return userRepository.findByEmail(email) | ||
} | ||
} |
4 changes: 2 additions & 2 deletions
4
src/main/kotlin/com/wafflestudio/toyproject/memoWithTags/user/GoogleUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.