diff --git a/komga-webui/src/services/komga-filesystem.service.ts b/komga-webui/src/services/komga-filesystem.service.ts index 652ef0bd21..730d3cdb6b 100644 --- a/komga-webui/src/services/komga-filesystem.service.ts +++ b/komga-webui/src/services/komga-filesystem.service.ts @@ -3,7 +3,7 @@ import { AxiosInstance } from 'axios' const API_FILESYSTEM = '/api/v1/filesystem' export default class KomgaFilesystemService { - private http: AxiosInstance; + private http: AxiosInstance constructor (http: AxiosInstance) { this.http = http @@ -11,13 +11,9 @@ export default class KomgaFilesystemService { async getDirectoryListing (path: String = ''): Promise { try { - return (await this.http.get(API_FILESYSTEM, - { - params: { - path: path - } - } - )).data + return (await this.http.post(API_FILESYSTEM, { + path: path + })).data } catch (e) { let msg = 'An error occurred while trying to retrieve directory listing' if (e.response.data.message) { diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/FileSystemController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/FileSystemController.kt index 7fcb3bcf68..1399b97024 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/FileSystemController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/FileSystemController.kt @@ -4,9 +4,9 @@ import com.fasterxml.jackson.annotation.JsonInclude import org.springframework.http.HttpStatus import org.springframework.http.MediaType import org.springframework.security.access.prepost.PreAuthorize -import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +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 import org.springframework.web.server.ResponseStatusException import java.nio.file.FileSystems @@ -21,50 +21,54 @@ class FileSystemController { private val fs = FileSystems.getDefault() - @GetMapping + @PostMapping fun getDirectoryListing( - @RequestParam(name = "path", required = false) path: String? + @RequestBody(required = false) request: DirectoryRequestDto = DirectoryRequestDto() ): DirectoryListingDto = - if (path.isNullOrEmpty()) { + if (request.path.isEmpty()) { + DirectoryListingDto( + directories = fs.rootDirectories.map { it.toDto() } + ) + } else { + val p = fs.getPath(request.path) + if (!p.isAbsolute) throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Path must be absolute") + try { DirectoryListingDto( - directories = fs.rootDirectories.map { it.toDto() } + parent = (p.parent ?: "").toString(), + directories = Files.list(p).use { dirStream -> + dirStream.asSequence() + .filter { Files.isDirectory(it) } + .filter { !Files.isHidden(it) } + .sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.toString() }) + .map { it.toDto() } + .toList() + } ) - } else { - val p = fs.getPath(path) - if (!p.isAbsolute) throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Path must be absolute") - try { - DirectoryListingDto( - parent = (p.parent ?: "").toString(), - directories = Files.list(p).use { dirStream -> - dirStream.asSequence() - .filter { Files.isDirectory(it) } - .filter { !Files.isHidden(it) } - .sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.toString() }) - .map { it.toDto() } - .toList() - } - ) - } catch (e: Exception) { - throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Path does not exist") - } + } catch (e: Exception) { + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Path does not exist") } + } } +data class DirectoryRequestDto( + val path: String = "" +) + @JsonInclude(JsonInclude.Include.NON_NULL) data class DirectoryListingDto( - val parent: String? = null, - val directories: List + val parent: String? = null, + val directories: List ) data class PathDto( - val type: String, - val name: String, - val path: String + val type: String, + val name: String, + val path: String ) fun Path.toDto(): PathDto = - PathDto( - type = if (Files.isDirectory(this)) "directory" else "file", - name = (fileName ?: this).toString(), - path = toString() - ) + PathDto( + type = if (Files.isDirectory(this)) "directory" else "file", + name = (fileName ?: this).toString(), + path = toString() + ) diff --git a/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/FileSystemControllerTest.kt b/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/FileSystemControllerTest.kt index 603c342162..7b05236392 100644 --- a/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/FileSystemControllerTest.kt +++ b/komga/src/test/kotlin/org/gotson/komga/interfaces/rest/FileSystemControllerTest.kt @@ -5,11 +5,12 @@ import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.MediaType import org.springframework.security.test.context.support.WithAnonymousUser import org.springframework.security.test.context.support.WithMockUser import org.springframework.test.context.junit.jupiter.SpringExtension import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.post import java.nio.file.Files @ExtendWith(SpringExtension::class) @@ -23,22 +24,23 @@ class FileSystemControllerTest( @Test @WithAnonymousUser fun `given anonymous user when getDirectoryListing then return unauthorized`() { - mockMvc.get(route) + mockMvc.post(route) .andExpect { status { isUnauthorized } } } @Test @WithMockUser fun `given regular user when getDirectoryListing then return forbidden`() { - mockMvc.get(route) + mockMvc.post(route) .andExpect { status { isForbidden } } } @Test @WithMockUser(roles = ["USER", "ADMIN"]) fun `given relative path param when getDirectoryListing then return bad request`() { - mockMvc.get(route) { - param("path", ".") + mockMvc.post(route) { + contentType = MediaType.APPLICATION_JSON + content = "." }.andExpect { status { isBadRequest } } } @@ -48,8 +50,9 @@ class FileSystemControllerTest( val parent = Files.createTempDirectory(null) Files.delete(parent) - mockMvc.get(route) { - param("path", parent.toString()) + mockMvc.post(route) { + contentType = MediaType.APPLICATION_JSON + content = parent.toString() }.andExpect { status { isBadRequest } } } }