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>
|
||||
|
||||
@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 findByIdIn(ids: Collection<UUID>): List<RoomImage>
|
||||
fun existsByRoomIdAndContentHash(roomId: UUID, contentHash: String): Boolean
|
||||
|
||||
@@ -28,6 +28,7 @@ class FirebaseAuthFilter(
|
||||
return path.matches(Regex("^/properties/[^/]+/rooms/[^/]+/images/[^/]+/file$"))
|
||||
|| path.matches(Regex("^/properties/[^/]+/rooms/[^/]+/images$"))
|
||||
|| path.matches(Regex("^/properties/[^/]+/room-types$"))
|
||||
|| path.matches(Regex("^/properties/[^/]+/room-types/[^/]+/images$"))
|
||||
|| (path == "/image-tags" && request.method.equals("GET", true))
|
||||
|| path == "/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").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("/icons/png").permitAll()
|
||||
it.requestMatchers("/icons/png/*").permitAll()
|
||||
|
||||
Reference in New Issue
Block a user