Add room type images list endpoint
All checks were successful
build-and-deploy / build-deploy (push) Successful in 32s
All checks were successful
build-and-deploy / build-deploy (push) Successful in 32s
This commit is contained in:
@@ -0,0 +1,83 @@
|
|||||||
|
package com.android.trisolarisserver.controller
|
||||||
|
|
||||||
|
import com.android.trisolarisserver.controller.dto.RoomImageResponse
|
||||||
|
import com.android.trisolarisserver.models.room.RoomImage
|
||||||
|
import com.android.trisolarisserver.models.room.RoomImageTag
|
||||||
|
import com.android.trisolarisserver.repo.RoomImageRepo
|
||||||
|
import com.android.trisolarisserver.repo.RoomTypeRepo
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
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.RestController
|
||||||
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/properties/{propertyId}/room-types/{roomTypeCode}/images")
|
||||||
|
class RoomTypeImages(
|
||||||
|
private val roomTypeRepo: RoomTypeRepo,
|
||||||
|
private val roomImageRepo: RoomImageRepo,
|
||||||
|
@org.springframework.beans.factory.annotation.Value("\${storage.rooms.publicBaseUrl}")
|
||||||
|
private val publicBaseUrl: String
|
||||||
|
) {
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
fun listByRoomType(
|
||||||
|
@PathVariable propertyId: UUID,
|
||||||
|
@PathVariable roomTypeCode: String
|
||||||
|
): List<RoomImageResponse> {
|
||||||
|
val roomType = roomTypeRepo.findByPropertyIdAndCodeIgnoreCase(propertyId, roomTypeCode)
|
||||||
|
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Room type not found")
|
||||||
|
|
||||||
|
val images = roomImageRepo.findByPropertyIdAndRoomTypeCodeOrdered(propertyId, roomType.code).toMutableList()
|
||||||
|
if (images.isEmpty()) return emptyList()
|
||||||
|
|
||||||
|
val missing = mutableListOf<RoomImage>()
|
||||||
|
val present = mutableListOf<RoomImage>()
|
||||||
|
for (img in images) {
|
||||||
|
val originalExists = Files.exists(Paths.get(img.originalPath))
|
||||||
|
if (!originalExists) {
|
||||||
|
missing.add(img)
|
||||||
|
try {
|
||||||
|
Files.deleteIfExists(Paths.get(img.thumbnailPath))
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
present.add(img)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (missing.isNotEmpty()) {
|
||||||
|
roomImageRepo.deleteAll(missing)
|
||||||
|
}
|
||||||
|
return present.map { it.toResponse(publicBaseUrl) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RoomImage.toResponse(baseUrl: String): RoomImageResponse {
|
||||||
|
val id = id ?: throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Image id missing")
|
||||||
|
return RoomImageResponse(
|
||||||
|
id = id,
|
||||||
|
propertyId = property.id!!,
|
||||||
|
roomId = room.id!!,
|
||||||
|
roomTypeCode = roomTypeCode,
|
||||||
|
url = "$baseUrl/properties/${property.id}/rooms/${room.id}/images/$id/file",
|
||||||
|
thumbnailUrl = "$baseUrl/properties/${property.id}/rooms/${room.id}/images/$id/file?size=thumb",
|
||||||
|
contentType = contentType,
|
||||||
|
sizeBytes = sizeBytes,
|
||||||
|
tags = tags.map { it.toResponse() }.toSet(),
|
||||||
|
roomSortOrder = roomSortOrder,
|
||||||
|
roomTypeSortOrder = roomTypeSortOrder,
|
||||||
|
createdAt = createdAt.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RoomImageTag.toResponse(): com.android.trisolarisserver.controller.dto.RoomImageTagResponse {
|
||||||
|
val id = id ?: throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Tag id missing")
|
||||||
|
return com.android.trisolarisserver.controller.dto.RoomImageTagResponse(
|
||||||
|
id = id,
|
||||||
|
name = name
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -37,6 +37,20 @@ interface RoomImageRepo : JpaRepository<RoomImage, UUID> {
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
fun findByRoomTypeCodeForReorder(@Param("roomTypeCode") roomTypeCode: String): List<RoomImage>
|
fun findByRoomTypeCodeForReorder(@Param("roomTypeCode") roomTypeCode: String): List<RoomImage>
|
||||||
|
|
||||||
|
@org.springframework.data.jpa.repository.EntityGraph(attributePaths = ["tags"])
|
||||||
|
@Query(
|
||||||
|
"""
|
||||||
|
select ri
|
||||||
|
from RoomImage ri
|
||||||
|
where ri.property.id = :propertyId and ri.roomTypeCode = :roomTypeCode
|
||||||
|
order by case when ri.roomTypeSortOrder is null then 1 else 0 end, ri.roomTypeSortOrder asc, ri.createdAt desc
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
fun findByPropertyIdAndRoomTypeCodeOrdered(
|
||||||
|
@Param("propertyId") propertyId: UUID,
|
||||||
|
@Param("roomTypeCode") roomTypeCode: String
|
||||||
|
): List<RoomImage>
|
||||||
fun findByIdAndRoomIdAndPropertyId(id: UUID, roomId: UUID, propertyId: UUID): RoomImage?
|
fun findByIdAndRoomIdAndPropertyId(id: UUID, roomId: UUID, propertyId: UUID): RoomImage?
|
||||||
fun findByIdIn(ids: Collection<UUID>): List<RoomImage>
|
fun findByIdIn(ids: Collection<UUID>): List<RoomImage>
|
||||||
fun existsByRoomIdAndContentHash(roomId: UUID, contentHash: String): Boolean
|
fun existsByRoomIdAndContentHash(roomId: UUID, contentHash: String): Boolean
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class FirebaseAuthFilter(
|
|||||||
return path.matches(Regex("^/properties/[^/]+/rooms/[^/]+/images/[^/]+/file$"))
|
return path.matches(Regex("^/properties/[^/]+/rooms/[^/]+/images/[^/]+/file$"))
|
||||||
|| path.matches(Regex("^/properties/[^/]+/rooms/[^/]+/images$"))
|
|| path.matches(Regex("^/properties/[^/]+/rooms/[^/]+/images$"))
|
||||||
|| path.matches(Regex("^/properties/[^/]+/room-types$"))
|
|| path.matches(Regex("^/properties/[^/]+/room-types$"))
|
||||||
|
|| path.matches(Regex("^/properties/[^/]+/room-types/[^/]+/images$"))
|
||||||
|| (path == "/image-tags" && request.method.equals("GET", true))
|
|| (path == "/image-tags" && request.method.equals("GET", true))
|
||||||
|| path == "/icons/png"
|
|| path == "/icons/png"
|
||||||
|| path.matches(Regex("^/icons/png/[^/]+$"))
|
|| path.matches(Regex("^/icons/png/[^/]+$"))
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class SecurityConfig(
|
|||||||
it.requestMatchers("/properties/*/rooms/*/images/*/file").permitAll()
|
it.requestMatchers("/properties/*/rooms/*/images/*/file").permitAll()
|
||||||
it.requestMatchers("/properties/*/rooms/*/images").permitAll()
|
it.requestMatchers("/properties/*/rooms/*/images").permitAll()
|
||||||
it.requestMatchers("/properties/*/room-types").permitAll()
|
it.requestMatchers("/properties/*/room-types").permitAll()
|
||||||
|
it.requestMatchers("/properties/*/room-types/*/images").permitAll()
|
||||||
it.requestMatchers(org.springframework.http.HttpMethod.GET, "/image-tags").permitAll()
|
it.requestMatchers(org.springframework.http.HttpMethod.GET, "/image-tags").permitAll()
|
||||||
it.requestMatchers("/icons/png").permitAll()
|
it.requestMatchers("/icons/png").permitAll()
|
||||||
it.requestMatchers("/icons/png/*").permitAll()
|
it.requestMatchers("/icons/png/*").permitAll()
|
||||||
|
|||||||
Reference in New Issue
Block a user