fix(add library): special characters handling

some directories with special characters could not be explored and selected
This commit is contained in:
Gauthier Roebroeck 2020-03-18 15:39:37 +08:00
parent ca03111b0b
commit 15afa93431
3 changed files with 52 additions and 49 deletions

View file

@ -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<DirectoryListingDto> {
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) {

View file

@ -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<PathDto>
val parent: String? = null,
val directories: List<PathDto>
)
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()
)

View file

@ -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 } }
}
}