Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler
* @Valid 검증 실패 → 400
* throw IllegalArgumentException("메시지") → 400
* throw NoSuchElementException("메시지") → 404
* throw IllegalStateException("메시지") → 409
* 기타 모든 예외 → 500
*/
@ControllerAdvice
Expand Down Expand Up @@ -41,6 +42,12 @@ class GlobalExceptionHandler {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ApiResponse(ex.message ?: "데이터를 찾을 수 없습니다"))
}

@ExceptionHandler(IllegalStateException::class)
fun handleIllegalState(ex: IllegalStateException): ResponseEntity<ApiResponse<Void>> {
logger.warn("부적절한 상태: {}", ex.message)
return ResponseEntity.status(HttpStatus.CONFLICT).body(ApiResponse(ex.message ?: "요청을 처리할 수 없는 상태입니다"))
}

@ExceptionHandler(Exception::class)
fun handleGenericException(
ex: Exception,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.back.koreaTravelGuide.common.security

import org.springframework.security.core.Authentication

fun Authentication.getUserId(): Long {
if (principal is Long) {
return principal as Long
}
throw IllegalStateException("인증된 사용자 ID를 찾을 수 없거나 타입이 올바르지 않습니다.")
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.back.koreaTravelGuide.domain.auth.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.common.security.getUserId
import com.back.koreaTravelGuide.domain.auth.dto.request.UserRoleUpdateRequest
import com.back.koreaTravelGuide.domain.auth.dto.response.AccessTokenResponse
import com.back.koreaTravelGuide.domain.auth.dto.response.LoginResponse
Expand All @@ -10,7 +11,7 @@ import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.security.core.Authentication
import org.springframework.web.bind.annotation.CookieValue
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
Expand Down Expand Up @@ -45,9 +46,10 @@ class AuthController(
@Operation(summary = "신규 사용자 역할 선택")
@PostMapping("/role")
fun updateUserRole(
@AuthenticationPrincipal userId: Long,
authentication: Authentication,
@RequestBody request: UserRoleUpdateRequest,
): ResponseEntity<ApiResponse<LoginResponse>> {
val userId = authentication.getUserId()
val loginResponse = authService.updateRoleAndLogin(userId, request.role)
return ResponseEntity.ok(ApiResponse("역할이 선택되었으며 로그인에 성공했습니다.", loginResponse))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.back.koreaTravelGuide.domain.rate.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.common.security.getUserId
import com.back.koreaTravelGuide.domain.rate.dto.GuideRatingSummaryResponse
import com.back.koreaTravelGuide.domain.rate.dto.RateRequest
import com.back.koreaTravelGuide.domain.rate.dto.RateResponse
Expand All @@ -10,7 +11,7 @@ import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.security.core.Authentication
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PutMapping
Expand All @@ -26,31 +27,32 @@ class RateController(
@Operation(summary = "가이드 평가 생성/수정")
@PutMapping("/guides/{guideId}")
fun rateGuide(
@AuthenticationPrincipal raterUserId: Long,
authentication: Authentication,
@PathVariable guideId: Long,
@RequestBody request: RateRequest,
): ResponseEntity<ApiResponse<RateResponse>> {
val raterUserId = authentication.getUserId()
val rate = rateService.rateGuide(raterUserId, guideId, request.rating, request.comment)
return ResponseEntity.ok(ApiResponse("가이드 평가가 등록되었습니다.", RateResponse.from(rate)))
}

@Operation(summary = "AI 채팅 세션 평가 생성/수정")
@PutMapping("/aichat/sessions/{sessionId}")
fun rateAiSession(
@AuthenticationPrincipal raterUserId: Long,
authentication: Authentication,
@PathVariable sessionId: Long,
@RequestBody request: RateRequest,
): ResponseEntity<ApiResponse<RateResponse>> {
val raterUserId = authentication.getUserId()
val rate = rateService.rateAiSession(raterUserId, sessionId, request.rating, request.comment)
return ResponseEntity.ok(ApiResponse("AI 채팅 평가가 등록되었습니다.", RateResponse.from(rate)))
}

@Operation(summary = "내가 받은 가이드 평가 조회")
@GetMapping("/guides/my")
@PreAuthorize("hasRole('GUIDE')")
fun getMyGuideRatings(
@AuthenticationPrincipal guideId: Long,
): ResponseEntity<ApiResponse<GuideRatingSummaryResponse>> {
fun getMyGuideRatings(authentication: Authentication): ResponseEntity<ApiResponse<GuideRatingSummaryResponse>> {
val guideId = authentication.getUserId()
val summary = rateService.getMyGuideRatingSummary(guideId)
return ResponseEntity.ok(ApiResponse("내 가이드 평점 정보를 조회했습니다.", summary))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.back.koreaTravelGuide.domain.guide.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.common.security.getUserId
import com.back.koreaTravelGuide.domain.guide.service.GuideService
import com.back.koreaTravelGuide.domain.user.dto.request.GuideUpdateRequest
import com.back.koreaTravelGuide.domain.user.dto.response.GuideResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.security.core.Authentication
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
Expand Down Expand Up @@ -42,9 +43,10 @@ class GuideController(
@PreAuthorize("hasRole('GUIDE')")
@PatchMapping("/me")
fun updateMyGuideProfile(
@AuthenticationPrincipal guideId: Long,
authentication: Authentication,
@RequestBody request: GuideUpdateRequest,
): ResponseEntity<ApiResponse<GuideResponse>> {
val guideId = authentication.getUserId()
val updatedGuideProfile = guideService.updateGuideProfile(guideId, request)
return ResponseEntity.ok(ApiResponse("가이드 정보가 성공적으로 수정되었습니다.", updatedGuideProfile))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.back.koreaTravelGuide.domain.user.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.common.security.getUserId
import com.back.koreaTravelGuide.domain.user.dto.request.UserUpdateRequest
import com.back.koreaTravelGuide.domain.user.dto.response.UserResponse
import com.back.koreaTravelGuide.domain.user.service.UserService
import io.swagger.v3.oas.annotations.Operation
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.security.core.Authentication
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
Expand All @@ -21,28 +22,27 @@ class UserController(
) {
@Operation(summary = "내 정보 조회")
@GetMapping("/me")
fun getMyProfile(
@AuthenticationPrincipal userId: Long,
): ResponseEntity<ApiResponse<UserResponse>> {
fun getMyProfile(authentication: Authentication): ResponseEntity<ApiResponse<UserResponse>> {
val userId = authentication.getUserId()
val userProfile = userService.getUserProfileById(userId)
return ResponseEntity.ok(ApiResponse("내 정보를 성공적으로 조회했습니다.", userProfile))
}

@Operation(summary = "내 프로필 수정")
@PatchMapping("/me")
fun updateMyProfile(
@AuthenticationPrincipal userId: Long,
authentication: Authentication,
@RequestBody request: UserUpdateRequest,
): ResponseEntity<ApiResponse<UserResponse>> {
val userId = authentication.getUserId()
val updatedProfile = userService.updateUserProfile(userId, request)
return ResponseEntity.ok(ApiResponse("정보가 성공적으로 수정되었습니다.", updatedProfile))
}

@Operation(summary = "회원 탈퇴")
@DeleteMapping("/me")
fun deleteMe(
@AuthenticationPrincipal userId: Long,
): ResponseEntity<ApiResponse<Unit>> {
fun deleteMe(authentication: Authentication): ResponseEntity<ApiResponse<Unit>> {
val userId = authentication.getUserId()
userService.deleteUser(userId)
return ResponseEntity.ok(ApiResponse("회원 탈퇴가 완료되었습니다."))
}
Expand Down