package kr.co.vividnext.sodalive.member import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.marketing.AdTrackingHistoryType import kr.co.vividnext.sodalive.marketing.AdTrackingService import kr.co.vividnext.sodalive.member.block.MemberBlockRequest import kr.co.vividnext.sodalive.member.following.CreatorFollowRequest import kr.co.vividnext.sodalive.member.login.LoginRequest import kr.co.vividnext.sodalive.member.login.LoginResponse import kr.co.vividnext.sodalive.member.login.SocialLoginRequest import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest import kr.co.vividnext.sodalive.member.signUp.SignUpRequestV2 import kr.co.vividnext.sodalive.member.social.google.GoogleAuthService import kr.co.vividnext.sodalive.member.social.kakao.KakaoAuthService import org.springframework.data.domain.Pageable import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.security.core.userdetails.User import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PutMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestHeader import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RequestPart import org.springframework.web.bind.annotation.RestController import org.springframework.web.multipart.MultipartFile @RestController @RequestMapping("/member") class MemberController( private val service: MemberService, private val kakaoAuthService: KakaoAuthService, private val googleAuthService: GoogleAuthService, private val trackingService: AdTrackingService ) { @GetMapping("/check/email") fun checkEmail(@RequestParam email: String) = service.duplicateCheckEmail(email) @GetMapping("/check/nickname") fun checkNickname(@RequestParam nickname: String) = service.duplicateCheckNickname(nickname) @PutMapping("/change/nickname") fun changeNickname( @RequestBody profileUpdateRequest: ProfileUpdateRequest, @AuthenticationPrincipal user: User ) = ApiResponse.ok(service.updateNickname(profileUpdateRequest, user)) @PostMapping("/signup/v2") fun signupV2(@RequestBody request: SignUpRequestV2): ApiResponse { val response = service.signUpV2(request) if (!response.marketingPid.isNullOrBlank()) { trackingService.saveTrackingHistory( pid = response.marketingPid, type = AdTrackingHistoryType.SIGNUP, memberId = response.memberId ) } return ApiResponse.ok(message = "회원가입을 축하드립니다.", data = response.loginResponse) } @PostMapping("/signup") fun signUp( @RequestPart("profileImage", required = false) profileImage: MultipartFile? = null, @RequestPart("request") requestString: String ): ApiResponse { val response = service.signUp(profileImage, requestString) if (!response.marketingPid.isNullOrBlank()) { trackingService.saveTrackingHistory( pid = response.marketingPid, type = AdTrackingHistoryType.SIGNUP, memberId = response.memberId ) } return ApiResponse.ok(message = "회원가입을 축하드립니다.", data = response.loginResponse) } @PostMapping("/login") fun login(@RequestBody loginRequest: LoginRequest) = service.login(loginRequest) @PostMapping("/logout") fun logout( @RequestHeader("Authorization") token: String, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.logout(token.removePrefix("Bearer "), member.id!!)) } @PostMapping("/logout/all") fun logoutAll( @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.logoutAll(member.id!!)) } @GetMapping fun getMember( @RequestParam container: String, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.getMember(member.id!!, container)) } @GetMapping("/info") fun getMemberInfo( @RequestParam container: String?, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.getMemberInfo(member, container ?: "web")) } @PostMapping("/notification") fun updateNotificationSettings( @RequestBody request: UpdateNotificationSettingRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.updateNotificationSettings(request, member)) } @PutMapping("/push-token/update") fun updatePushToken( @RequestBody pushTokenUpdateRequest: PushTokenUpdateRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.updatePushToken( memberId = member.id!!, pushToken = pushTokenUpdateRequest.pushToken, container = pushTokenUpdateRequest.container ) ) } @PutMapping("/marketing-info/update") fun updateMarketingInfo( @RequestBody request: MarketingInfoUpdateRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") val memberId = member.id!! val marketingPid = service.updateMarketingInfo( memberId = memberId, adid = request.adid, pid = request.pid ) if (!marketingPid.isNullOrBlank()) { trackingService.saveTrackingHistory( pid = marketingPid, type = AdTrackingHistoryType.LOGIN, memberId = memberId ) } ApiResponse.ok(Unit) } @PutMapping("/adid/update") fun updateAdid( @RequestBody request: AdidUpdateRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.updateAdid( memberId = member.id!!, adid = request.adid ) ) } @GetMapping("/mypage") fun getMyPage( @RequestParam container: String, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.getMyPage(member, container)) } @PostMapping("/creator/follow") fun creatorFollow( @RequestBody request: CreatorFollowRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.creatorFollow( creatorId = request.creatorId, isNotify = request.isNotify ?: true, isActive = request.isActive ?: true, memberId = member.id!! ) ) } @PostMapping("/creator/unfollow") fun creatorUnFollow( @RequestBody request: CreatorFollowRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.creatorUnFollow(creatorId = request.creatorId, memberId = member.id!!)) } @GetMapping("/block/id") fun getBlockedMemberIdList( @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, pageable: Pageable ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.getBlockedMemberIdList(member.id!!)) } @GetMapping("/block") fun getBlockedMemberList( @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, pageable: Pageable ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok( service.getBlockedMemberList( member.id!!, offset = pageable.offset, limit = pageable.pageSize.toLong() ) ) } @PostMapping("/block") fun memberBlock( @RequestBody request: MemberBlockRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.memberBlock(request = request, memberId = member.id!!)) } @PostMapping("/unblock") fun memberUnBlock( @RequestBody request: MemberBlockRequest, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.memberUnBlock(request = request, memberId = member.id!!)) } @GetMapping("/search") fun searchMember( @RequestParam nickname: String, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.searchMember(nickname = nickname, member = member)) } @PostMapping("/sign_out") fun signOut( @RequestBody signOutRequest: SignOutRequest, @AuthenticationPrincipal user: User ) = ApiResponse.ok(service.signOut(signOutRequest, user), "정상적으로 탈퇴 처리되었습니다.") @GetMapping("/change/nickname/price") fun getChangeNicknamePrice( @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.getChangeNicknamePrice(memberId = member.id!!)) } @PutMapping fun profileUpdate( @RequestBody profileUpdateRequest: ProfileUpdateRequest, @AuthenticationPrincipal user: User ) = ApiResponse.ok(service.profileUpdate(profileUpdateRequest, user)) @PostMapping("/image") fun profileImageUpdate( @RequestParam("image") multipartFile: MultipartFile, @AuthenticationPrincipal user: User ) = ApiResponse.ok(service.profileImageUpdate(multipartFile, user)) @PostMapping("/forgot-password") fun forgotPassword( @RequestBody request: ForgotPasswordRequest ) = ApiResponse.ok(service.forgotPassword(request)) @GetMapping("/profile/{id}") fun getMemberProfile( @PathVariable id: Long, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? ) = run { if (member == null) throw SodaException("로그인 정보를 확인해주세요.") ApiResponse.ok(service.getMemberProfile(memberId = id, myMemberId = member.id!!)) } @PostMapping("/login/google") fun loginGoogle( @RequestHeader("Authorization") authHeader: String, @RequestBody request: SocialLoginRequest ): ApiResponse { if (!authHeader.startsWith("Bearer ")) { throw SodaException("구글 로그인을 하지 못했습니다. 다시 시도해 주세요") } val token = authHeader.substring(7) val response = googleAuthService.authenticate(token, request.container, request.marketingPid) if (!response.marketingPid.isNullOrBlank()) { trackingService.saveTrackingHistory( pid = response.marketingPid, type = AdTrackingHistoryType.SIGNUP, memberId = response.memberId ) } return ApiResponse.ok(message = "회원가입을 축하드립니다.", data = response.loginResponse) } @PostMapping("/login/kakao") fun loginKakao( @RequestHeader("Authorization") authHeader: String, @RequestBody request: SocialLoginRequest ): ApiResponse { if (!authHeader.startsWith("Bearer ")) { throw SodaException("카카오 로그인을 하지 못했습니다. 다시 시도해 주세요") } val token = authHeader.substring(7) val response = kakaoAuthService.authenticate(token, request.container, request.marketingPid) if (!response.marketingPid.isNullOrBlank()) { trackingService.saveTrackingHistory( pid = response.marketingPid, type = AdTrackingHistoryType.SIGNUP, memberId = response.memberId ) } return ApiResponse.ok(message = "회원가입을 축하드립니다.", data = response.loginResponse) } }