Images can now be deleted

This commit is contained in:
neviyn 2021-05-09 21:06:46 +01:00
parent c4c44ad4da
commit 4e3c60925c
5 changed files with 37 additions and 1 deletions

View File

@ -6,6 +6,7 @@ import org.springframework.data.domain.PageRequest
import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.stereotype.Controller import org.springframework.stereotype.Controller
import org.springframework.ui.Model import org.springframework.ui.Model
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PathVariable
@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.multipart.MultipartFile import org.springframework.web.multipart.MultipartFile
import java.security.MessageDigest import java.security.MessageDigest
import java.util.* import java.util.*
import javax.transaction.Transactional
import javax.validation.Valid import javax.validation.Valid
import javax.validation.constraints.NotEmpty import javax.validation.constraints.NotEmpty
@ -38,12 +40,13 @@ class BaseController
} }
@GetMapping("/view/{id}") @GetMapping("/view/{id}")
fun viewSingleImage(@PathVariable id: Long, model: Model) : String { fun viewSingleImage(@PathVariable id: Long, model: Model, @AuthenticationPrincipal userDetails: CustomUserDetails?) : String {
val image = imageRepository.findById(id).get() val image = imageRepository.findById(id).get()
val tagData = image.tags.sortedBy { it.tag } val tagData = image.tags.sortedBy { it.tag }
model.addAttribute("image", image) model.addAttribute("image", image)
model.addAttribute("tags", tagData) model.addAttribute("tags", tagData)
model.addAttribute("title", tagData.joinToString { it.tag }) model.addAttribute("title", tagData.joinToString { it.tag })
model.addAttribute("isUploader", (userDetails != null && (userDetails.authorities.any { it.authority == "ADMIN" } || userDetails.getId() == image.uploader.id)))
return "single" return "single"
} }
} }
@ -152,6 +155,24 @@ class UploadController
imageRepository.save(Image("$hash.$extension", user, tagData)) imageRepository.save(Image("$hash.$extension", user, tagData))
return "upload" // TODO: Show success on page return "upload" // TODO: Show success on page
} }
@DeleteMapping("/d/{imageID}")
@Transactional
fun deleteUpload(@PathVariable imageID: Long, @AuthenticationPrincipal userDetails: CustomUserDetails) : String {
val target = imageRepository.findById(imageID)
if(target.isEmpty) return "gallery" // No image with ID
val rTarget = target.get()
return if(userDetails.authorities.any { it.authority == "ADMIN" } || rTarget.uploader.id == userDetails.getId()) {
rTarget.tags.map { it.amount = it.amount - 1 }
tagRepository.saveAll(rTarget.tags)
imageRepository.deleteTagAssociations(rTarget.id)
storage.deleteImageFile(rTarget.filename)
imageRepository.delete(rTarget)
"gallery" // Success
} else {
"gallery" // Can only delete someone elses images if you are an admin
}
}
} }
val digest: MessageDigest = MessageDigest.getInstance("SHA-512/256") val digest: MessageDigest = MessageDigest.getInstance("SHA-512/256")

View File

@ -12,6 +12,7 @@ interface FileSystemStorage {
* Add a file to the filesystem with [name] and file [extension] * Add a file to the filesystem with [name] and file [extension]
*/ */
fun addImageFile(name: String, extension: String, data: ByteArray) fun addImageFile(name: String, extension: String, data: ByteArray)
fun deleteImageFile(name: String)
} }
@ -27,4 +28,12 @@ class FileSystemStorageService
Thumbnails.of(outputFile).size(200, 200).toFiles(Rename.PREFIX_DOT_THUMBNAIL) Thumbnails.of(outputFile).size(200, 200).toFiles(Rename.PREFIX_DOT_THUMBNAIL)
} }
override fun deleteImageFile(name: String) {
File(imageConfigurationProperties.directory, name).delete()
File(imageConfigurationProperties.directory, "thumbnail.$name").delete()
}
} }

View File

@ -3,6 +3,7 @@ package uk.co.neviyn.booru
import org.springframework.data.domain.Page import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.CrudRepository import org.springframework.data.repository.CrudRepository
@ -23,6 +24,7 @@ interface ImageRepository : JpaRepository<Image, Long> {
fun findAllByTagsContainingOrderById(tag: Tag, pageable: Pageable): Page<Image> fun findAllByTagsContainingOrderById(tag: Tag, pageable: Pageable): Page<Image>
@Suppress("SqlResolve") @Suppress("SqlResolve")
@Modifying
@Query(value = "DELETE FROM BOORU.TAG_IMAGE WHERE IMAGE_ID = ?1", nativeQuery = true) @Query(value = "DELETE FROM BOORU.TAG_IMAGE WHERE IMAGE_ID = ?1", nativeQuery = true)
fun deleteTagAssociations(imagesID: Long) fun deleteTagAssociations(imagesID: Long)
} }

View File

@ -1,4 +1,5 @@
spring.jpa.hibernate.ddl-auto=validate spring.jpa.hibernate.ddl-auto=validate
spring.datasource.initialization-mode=always spring.datasource.initialization-mode=always
spring.jpa.properties.hibernate.default_schema=booru spring.jpa.properties.hibernate.default_schema=booru
spring.mvc.hiddenmethod.filter.enabled=true
images.types=jpg,png,gif images.types=jpg,png,gif

View File

@ -27,6 +27,9 @@
<ul> <ul>
<li th:each="tag : ${tags}"><a class="text-decoration-none" th:href="${#mvc.url('IC#getGalleryPage').arg(1, tag.tag).build()}" th:text="${tag.tag} + ' ' + ${tag.amount}">tag</a></li> <li th:each="tag : ${tags}"><a class="text-decoration-none" th:href="${#mvc.url('IC#getGalleryPage').arg(1, tag.tag).build()}" th:text="${tag.tag} + ' ' + ${tag.amount}">tag</a></li>
</ul> </ul>
<form th:if="${isUploader}" th:action="'/upload/d/' + ${image.id}" th:method="delete">
<button type="submit">Delete</button>
</form>
</div> </div>
<div class="col-8"> <div class="col-8">
<img th:src="'/i/' + ${image.filename}" th:alt="${image.filename}" class="w-100"> <img th:src="'/i/' + ${image.filename}" th:alt="${image.filename}" class="w-100">