diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/config/SecurityConfig.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/config/SecurityConfig.kt index 8b7e399..78b1325 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/config/SecurityConfig.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/config/SecurityConfig.kt @@ -86,6 +86,7 @@ class SecurityConfig( authorize("/api/oauth2/**", permitAll) authorize(HttpMethod.GET, "/api/v1/rooms/main/**", permitAll) authorize(HttpMethod.GET, "/api/v1/reservations/availability/**", permitAll) + authorize(HttpMethod.GET, "/api/v1/reservations/user/**", permitAll) authorize(HttpMethod.GET, "/api/v1/reviews/**", permitAll) authorize("/error", permitAll) authorize("/redirect", permitAll) diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/profile/controller/ProfileController.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/profile/controller/ProfileController.kt index bbb7d8d..20aa5e0 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/profile/controller/ProfileController.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/profile/controller/ProfileController.kt @@ -53,10 +53,14 @@ class ProfileController( data class UpdateProfileRequest( val nickname: String, - val bio: String + val bio: String, + val showMyReviews: Boolean, + val showMyReservations: Boolean ) data class CreateProfileRequest( val nickname: String, - val bio: String + val bio: String, + val showMyReviews: Boolean, + val showMyReservations: Boolean ) diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/profile/persistence/ProfileEntity.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/profile/persistence/ProfileEntity.kt index dbc3db2..0823609 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/profile/persistence/ProfileEntity.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/profile/persistence/ProfileEntity.kt @@ -29,5 +29,11 @@ class ProfileEntity( var bio: String, @Column(nullable = false) - var isSuperHost: Boolean = false + var isSuperHost: Boolean = false, + + @Column(nullable = false) + var showMyReviews: Boolean = false, + + @Column(nullable = false) + var showMyReservations: Boolean = false ) diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/profile/service/ProfileServiceImpl.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/profile/service/ProfileServiceImpl.kt index 55337b1..a895b97 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/profile/service/ProfileServiceImpl.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/profile/service/ProfileServiceImpl.kt @@ -18,6 +18,7 @@ class ProfileServiceImpl( private val roomRepository: RoomRepository ) : ProfileService { + @Transactional override fun getCurrentUserProfile( user: UserEntity ): Profile { @@ -30,10 +31,12 @@ class ProfileServiceImpl( user: UserEntity, request: UpdateProfileRequest ): Profile { - val profile = profileRepository.findByUser(user) ?: throw ProfileNotFoundException() + val profile = profileRepository.findByUser(user) ?: ProfileEntity(user = user, nickname = "", bio = "") profile.nickname = request.nickname profile.bio = request.bio + profile.showMyReviews = request.showMyReviews + profile.showMyReservations = request.showMyReservations updateSuperHostStatus(profile) profileRepository.save(profile) @@ -50,7 +53,9 @@ class ProfileServiceImpl( val profile = ProfileEntity( user = user, nickname = request.nickname, - bio = request.bio + bio = request.bio, + showMyReviews = request.showMyReviews, + showMyReservations = request.showMyReservations ) updateSuperHostStatus(profile) diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/controller/ReservationController.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/controller/ReservationController.kt index 1871080..411a00c 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/controller/ReservationController.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/controller/ReservationController.kt @@ -5,10 +5,12 @@ import com.example.toyTeam6Airbnb.user.controller.PrincipalDetails import com.example.toyTeam6Airbnb.user.controller.User import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.security.core.context.SecurityContextHolder import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @@ -91,9 +93,18 @@ class ReservationController( @Operation(summary = "유저별 예약 조회", description = "특정 유저의 모든 예약 정보를 조회합니다") fun getReservationsByUser( @PathVariable userId: Long, - @RequestParam pageable: Pageable - ): ResponseEntity> { - val reservations = reservationService.getReservationsByUser(userId, pageable) + pageable: Pageable + ): ResponseEntity> { + val viewerId = + try { + val principalDetails = SecurityContextHolder.getContext().authentication.principal as PrincipalDetails + principalDetails.getUser().id + // logic for when the user is logged in + } catch (e: ClassCastException) { + // logic for when the user is not logged in + null + } + val reservations = reservationService.getReservationsByUser(viewerId, userId, pageable) return ResponseEntity.ok(reservations) } diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/persistence/ReservationRepository.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/persistence/ReservationRepository.kt index ec5043d..8860700 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/persistence/ReservationRepository.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/persistence/ReservationRepository.kt @@ -3,6 +3,8 @@ package com.example.toyTeam6Airbnb.reservation.persistence import com.example.toyTeam6Airbnb.room.persistence.RoomEntity import com.example.toyTeam6Airbnb.user.persistence.UserEntity import jakarta.persistence.LockModeType +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Lock import org.springframework.data.jpa.repository.Query @@ -15,5 +17,5 @@ interface ReservationRepository : JpaRepository { fun findAllByRoom(room: RoomEntity): List - fun findAllByUser(user: UserEntity): List + fun findAllByUser(user: UserEntity, pageable: Pageable): Page } diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationService.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationService.kt index 6bd8145..49b72ca 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationService.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationService.kt @@ -4,6 +4,7 @@ import com.example.toyTeam6Airbnb.reservation.controller.Reservation import com.example.toyTeam6Airbnb.reservation.controller.ReservationDTO import com.example.toyTeam6Airbnb.reservation.controller.RoomAvailabilityResponse import com.example.toyTeam6Airbnb.user.controller.User +import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import java.time.LocalDate import java.time.YearMonth @@ -36,9 +37,10 @@ interface ReservationService { ): Reservation fun getReservationsByUser( + viewerId: Long?, userId: Long, pageable: Pageable - ): List + ): Page // fun getReservationsByRoom( // roomId: Long diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationServiceImpl.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationServiceImpl.kt index 63193ea..8092dbb 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationServiceImpl.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/reservation/service/ReservationServiceImpl.kt @@ -19,6 +19,7 @@ import com.example.toyTeam6Airbnb.user.controller.User import com.example.toyTeam6Airbnb.user.persistence.UserRepository import jakarta.persistence.EntityManager import jakarta.persistence.LockModeType +import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service @@ -132,10 +133,11 @@ class ReservationServiceImpl( } @Transactional - override fun getReservationsByUser(userId: Long, pageable: Pageable): List { + override fun getReservationsByUser(viewerId: Long?, userId: Long, pageable: Pageable): Page { val userEntity = userRepository.findByIdOrNull(userId) ?: throw UserNotFoundException() + if (viewerId != userId && userEntity.profile?.showMyReservations != true) throw ReservationPermissionDenied() - return reservationRepository.findAllByUser(userEntity).map(ReservationDTO::fromEntity) + return reservationRepository.findAllByUser(userEntity, pageable).map(ReservationDTO::fromEntity) } // @Transactional diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/review/controller/ReviewController.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/review/controller/ReviewController.kt index 3215919..0cf790b 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/review/controller/ReviewController.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/review/controller/ReviewController.kt @@ -10,6 +10,7 @@ import org.springframework.data.domain.Pageable import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.security.core.context.SecurityContextHolder import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @@ -17,7 +18,6 @@ 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.RequestMapping -import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @@ -47,7 +47,7 @@ class ReviewController( @Operation(summary = "특정 방의 리뷰 조회", description = "특정 방의 모든 리뷰를 조회합니다") fun getReviewsByRoom( @PathVariable roomId: Long, - @RequestParam pageable: Pageable + pageable: Pageable ): ResponseEntity> { val reviews = reviewService.getReviewsByRoom(roomId, pageable) return ResponseEntity.ok(reviews) @@ -66,9 +66,18 @@ class ReviewController( @Operation(summary = "특정 유저의 리뷰 조회", description = "특정 유저의 모든 리뷰를 조회합니다") fun getReviewsByUser( @PathVariable userId: Long, - @RequestParam pageable: Pageable + pageable: Pageable ): ResponseEntity> { - val reviews = reviewService.getReviewsByUser(userId, pageable) + val viewerId = + try { + val principalDetails = SecurityContextHolder.getContext().authentication.principal as PrincipalDetails + principalDetails.getUser().id + // logic for when the user is logged in + } catch (e: ClassCastException) { + // logic for when the user is not logged in + null + } + val reviews = reviewService.getReviewsByUser(viewerId, userId, pageable) return ResponseEntity.ok(reviews) } diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewService.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewService.kt index 538f977..c8cd610 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewService.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewService.kt @@ -26,6 +26,7 @@ interface ReviewService { ): ReviewDTO fun getReviewsByUser( + viewerId: Long?, userId: Long, pageable: Pageable ): Page diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewServiceImpl.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewServiceImpl.kt index c4e23c9..bbd2f76 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewServiceImpl.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/review/service/ReviewServiceImpl.kt @@ -78,8 +78,9 @@ class ReviewServiceImpl( } @Transactional - override fun getReviewsByUser(userId: Long, pageable: Pageable): Page { - userRepository.findByIdOrNull(userId) ?: throw UserNotFoundException() + override fun getReviewsByUser(viewerId: Long?, userId: Long, pageable: Pageable): Page { + val userEntity = userRepository.findByIdOrNull(userId) ?: throw UserNotFoundException() + if (viewerId != userId && userEntity.profile?.showMyReviews != true) throw ReviewPermissionDeniedException() val reviewEntities = reviewRepository.findAllByUserId(userId, validatePageable(pageable)) diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/user/controller/UserController.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/user/controller/UserController.kt index 073edeb..649debc 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/user/controller/UserController.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/user/controller/UserController.kt @@ -31,7 +31,7 @@ class UserController( fun register( @RequestBody request: RegisterRequest ): ResponseEntity { - userService.register(username = request.username, password = request.password) + userService.register(request) return ResponseEntity.ok().build() } @@ -47,5 +47,9 @@ class UserController( data class RegisterRequest( val username: String, - val password: String + val password: String, + val nickname: String, + val bio: String, + val showMyReviews: Boolean, + val showMyReservations: Boolean ) diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserService.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserService.kt index 92ed4e1..379c0b4 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserService.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserService.kt @@ -1,10 +1,10 @@ package com.example.toyTeam6Airbnb.user.service +import com.example.toyTeam6Airbnb.user.controller.RegisterRequest import com.example.toyTeam6Airbnb.user.controller.User interface UserService { fun register( - username: String, - password: String + request: RegisterRequest ): User? } diff --git a/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserServiceImpl.kt b/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserServiceImpl.kt index 63d215e..23541c7 100644 --- a/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserServiceImpl.kt +++ b/src/main/kotlin/com/example/toyTeam6Airbnb/user/service/UserServiceImpl.kt @@ -1,7 +1,10 @@ package com.example.toyTeam6Airbnb.user.service +import com.example.toyTeam6Airbnb.profile.persistence.ProfileEntity +import com.example.toyTeam6Airbnb.profile.persistence.ProfileRepository import com.example.toyTeam6Airbnb.user.SignUpBadUsernameException import com.example.toyTeam6Airbnb.user.SignUpUsernameConflictException +import com.example.toyTeam6Airbnb.user.controller.RegisterRequest import com.example.toyTeam6Airbnb.user.controller.User import com.example.toyTeam6Airbnb.user.persistence.AuthProvider import com.example.toyTeam6Airbnb.user.persistence.UserEntity @@ -13,22 +16,29 @@ import org.springframework.stereotype.Service @Service class UserServiceImpl( private val userRepository: UserRepository, + private val profileRepository: ProfileRepository, private val passwordEncoder: PasswordEncoder ) : UserService { @Transactional override fun register( - username: String, - password: String + request: RegisterRequest ): User? { - if (username.startsWith("OAUTH")) throw SignUpBadUsernameException() - if (userRepository.existsByUsername(username)) throw SignUpUsernameConflictException() + if (request.username.startsWith("OAUTH")) throw SignUpBadUsernameException() + if (userRepository.existsByUsername(request.username)) throw SignUpUsernameConflictException() val userEntity = UserEntity( - username = username, - password = passwordEncoder.encode(password), + username = request.username, + password = passwordEncoder.encode(request.password), provider = AuthProvider.LOCAL ).let { userRepository.save(it) } + ProfileEntity( + user = userEntity, + nickname = request.nickname, + bio = request.bio, + showMyReviews = request.showMyReviews, + showMyReservations = request.showMyReservations + ).let { profileRepository.save(it) } return User.fromEntity(userEntity) } } diff --git a/src/test/kotlin/com/example/toyTeam6Airbnb/ReservationControllerTest.kt b/src/test/kotlin/com/example/toyTeam6Airbnb/ReservationControllerTest.kt index ab79f35..dfdaee4 100644 --- a/src/test/kotlin/com/example/toyTeam6Airbnb/ReservationControllerTest.kt +++ b/src/test/kotlin/com/example/toyTeam6Airbnb/ReservationControllerTest.kt @@ -1,6 +1,9 @@ package com.example.toyTeam6Airbnb import com.example.toyTeam6Airbnb.reservation.persistence.ReservationRepository +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired @@ -261,6 +264,96 @@ class ReservationControllerTest { .andReturn() } + @Test + fun `should get reservations by user`() { + val (user, token) = dataGenerator.generateUserAndToken() + val room = dataGenerator.generateRoom() + val reservation1 = dataGenerator.generateReservation(user, room) + val reservation2 = dataGenerator.generateReservation(user, room) + + val result = mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reservations/user/${user.id}?page=0&size=3") + .header("Authorization", "Bearer $token") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + .response + .contentAsString + + println(result) + // check result length + Assertions.assertEquals(getContentLength(result), 2) + + // check if all reviews are in the result + Assertions.assertEquals(getNthContentId(result, 0), reservation1.id) + Assertions.assertEquals(getNthContentId(result, 1), reservation2.id) + + // another user should not be able to see the reservations + val (user2, token2) = dataGenerator.generateUserAndToken() + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reservations/user/${user.id}?page=0&size=3") + .header("Authorization", "Bearer $token2") + ) + .andExpect(MockMvcResultMatchers.status().isForbidden) + .andReturn() + + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reservations/user/${user.id}?page=0&size=3") + ) + .andExpect(MockMvcResultMatchers.status().isForbidden) + .andReturn() + + // update user1's profile + val updateRequestBody = """ + { + "nickname": "newNickname", + "bio": "newBio", + "showMyReviews": true, + "showMyReservations": true + } + """.trimIndent() + mockMvc.perform( + MockMvcRequestBuilders.put("/api/v1/profile") + .contentType(MediaType.APPLICATION_JSON) + .content(updateRequestBody) + .header("Authorization", "Bearer $token") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + + // user2 should be able to see the reservations now + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reservations/user/${user.id}?page=0&size=3") + .header("Authorization", "Bearer $token2") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reservations/user/${user.id}?page=0&size=3") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + } + + fun getNthContentId(jsonString: String, n: Int): Long? { + val objectMapper = ObjectMapper() + val rootNode: JsonNode = objectMapper.readTree(jsonString) + val contentNode: JsonNode = rootNode.path("content") + return if (contentNode.isArray && contentNode.size() > n) { + contentNode[n].path("id").asLong() + } else { + null + } + } + + fun getContentLength(jsonString: String): Int { + val objectMapper = ObjectMapper() + val rootNode: JsonNode = objectMapper.readTree(jsonString) + val contentNode: JsonNode = rootNode.path("content") + return if (contentNode.isArray) contentNode.size() else 0 + } + @BeforeEach fun setUp() { dataGenerator.clearAll() diff --git a/src/test/kotlin/com/example/toyTeam6Airbnb/ReviewIntegrationTest.kt b/src/test/kotlin/com/example/toyTeam6Airbnb/ReviewIntegrationTest.kt index 7f66014..138cef9 100644 --- a/src/test/kotlin/com/example/toyTeam6Airbnb/ReviewIntegrationTest.kt +++ b/src/test/kotlin/com/example/toyTeam6Airbnb/ReviewIntegrationTest.kt @@ -3,6 +3,9 @@ package com.example.toyTeam6Airbnb import com.example.toyTeam6Airbnb.review.persistence.ReviewRepository import com.example.toyTeam6Airbnb.room.persistence.RoomRepository import com.example.toyTeam6Airbnb.user.persistence.UserRepository +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired @@ -135,4 +138,124 @@ class ReviewIntegrationTest { val responseContent = result.response.contentAsString println(responseContent) } + + @Test + fun `should get reviews by room`() { + val (user, token) = dataGenerator.generateUserAndToken() + val room = dataGenerator.generateRoom() + val reservation1 = dataGenerator.generateReservation(user, room) + val reservation2 = dataGenerator.generateReservation(user, room) + val review1 = dataGenerator.generateReview(reservation1) + val review2 = dataGenerator.generateReview(reservation2) + + val result = mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reviews/room/${room.id}?page=0&size=3") + .accept(MediaType.APPLICATION_JSON) + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + .response + .contentAsString + + // check result length + Assertions.assertEquals(getContentLength(result), 2) + + // check if all reviews are in the result + Assertions.assertEquals(getNthContentId(result, 0), review1.id) + Assertions.assertEquals(getNthContentId(result, 1), review2.id) + println(result) + } + + fun getNthContentId(jsonString: String, n: Int): Long? { + val objectMapper = ObjectMapper() + val rootNode: JsonNode = objectMapper.readTree(jsonString) + val contentNode: JsonNode = rootNode.path("content") + return if (contentNode.isArray && contentNode.size() > n) { + contentNode[n].path("id").asLong() + } else { + null + } + } + + fun getContentLength(jsonString: String): Int { + val objectMapper = ObjectMapper() + val rootNode: JsonNode = objectMapper.readTree(jsonString) + val contentNode: JsonNode = rootNode.path("content") + return if (contentNode.isArray) contentNode.size() else 0 + } + + @Test + fun `should get reviews by user`() { + val (user1, token1) = dataGenerator.generateUserAndToken() + val room = dataGenerator.generateRoom() + val reservation1 = dataGenerator.generateReservation(user1, room) + val reservation2 = dataGenerator.generateReservation(user1, room) + val review1 = dataGenerator.generateReview(reservation1) + val review2 = dataGenerator.generateReview(reservation2) + + // the owning user should be able to see all reviews + val result = mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reviews/user/${user1.id}?page=0&size=3") + .header("Authorization", "Bearer $token1") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + .response + .contentAsString + + // check result length + Assertions.assertEquals(getContentLength(result), 2) + + // check if all reviews are in the result + Assertions.assertEquals(getNthContentId(result, 0), review1.id) + Assertions.assertEquals(getNthContentId(result, 1), review2.id) + println(result) + + // another user should not be able to see the reviews + val (user2, token2) = dataGenerator.generateUserAndToken() + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reviews/user/${user1.id}?page=0&size=3") + .header("Authorization", "Bearer $token2") + ) + .andExpect(MockMvcResultMatchers.status().isForbidden) + .andReturn() + + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reviews/user/${user1.id}?page=0&size=3") + ) + .andExpect(MockMvcResultMatchers.status().isForbidden) + .andReturn() + + // update user1's profile + val updateRequestBody = """ + { + "nickname": "newNickname", + "bio": "newBio", + "showMyReviews": true, + "showMyReservations": true + } + """.trimIndent() + mockMvc.perform( + MockMvcRequestBuilders.put("/api/v1/profile") + .contentType(MediaType.APPLICATION_JSON) + .content(updateRequestBody) + .header("Authorization", "Bearer $token1") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + + // user2 should be able to see the reviews now + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reviews/user/${user1.id}?page=0&size=3") + .header("Authorization", "Bearer $token2") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + + mockMvc.perform( + MockMvcRequestBuilders.get("/api/v1/reviews/user/${user1.id}?page=0&size=3") + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + } } diff --git a/src/test/kotlin/com/example/toyTeam6Airbnb/UserControllerTest.kt b/src/test/kotlin/com/example/toyTeam6Airbnb/UserControllerTest.kt index 3b1db82..d965da5 100644 --- a/src/test/kotlin/com/example/toyTeam6Airbnb/UserControllerTest.kt +++ b/src/test/kotlin/com/example/toyTeam6Airbnb/UserControllerTest.kt @@ -30,7 +30,11 @@ constructor( val requestBody = """ { "username": "testuser", - "password": "password123" + "password": "password123", + "nickname": "testuser", + "bio": "Hello, I'm a test user!", + "showMyReviews": true, + "showMyReservations": true } """.trimIndent()