|
1 |
| -use super::{metadata::InodeMetaData, utils::validate_and_normalize_path}; |
| 1 | +use super::{ |
| 2 | + metadata::InodeMetaData, |
| 3 | + utils::{ |
| 4 | + get_parent_and_name, path_contains_rclone_modification_date, transform_to_ftp_error, |
| 5 | + validate_and_normalize_path, |
| 6 | + }, |
| 7 | +}; |
2 | 8 | use crate::auth::user::FileFighterUser;
|
3 | 9 | use async_trait::async_trait;
|
4 |
| -use chrono::NaiveDateTime; |
5 | 10 | use filefighter_api::ffs_api::{
|
6 | 11 | endpoints::{
|
7 | 12 | create_directory, delete_inode, download_file, get_contents_of_folder, get_inode,
|
8 | 13 | move_inode, rename_inode, set_last_modified_of_inode, upload_file,
|
9 | 14 | },
|
10 | 15 | ApiConfig,
|
11 |
| - ApiError::{self, ReqwestError, ResponseMalformed}, |
12 | 16 | };
|
13 | 17 | use libunftp::storage::{
|
14 | 18 | Error, ErrorKind, Fileinfo, Metadata, Result, StorageBackend, FEATURE_RESTART,
|
15 | 19 | };
|
16 | 20 | use std::{
|
17 | 21 | fmt::Debug,
|
18 |
| - path::{Component, Path, PathBuf}, |
| 22 | + path::{Path, PathBuf}, |
19 | 23 | };
|
20 | 24 | use tokio::io::AsyncRead;
|
21 | 25 | use tracing::{debug, error, instrument, warn};
|
@@ -258,110 +262,3 @@ impl StorageBackend<FileFighterUser> for FileFighter {
|
258 | 262 | }
|
259 | 263 | }
|
260 | 264 | }
|
261 |
| - |
262 |
| -fn get_parent_and_name(path: &Path) -> Result<(PathBuf, &str)> { |
263 |
| - match (path.parent(), path.file_name()) { |
264 |
| - (Some(parent), Some(name)) => Ok(( |
265 |
| - parent.to_path_buf(), |
266 |
| - name.to_str() |
267 |
| - .ok_or_else(|| Error::new(ErrorKind::LocalError, "Filename was not valid utf-8"))?, |
268 |
| - )), |
269 |
| - (_, _) => Err(Error::new( |
270 |
| - ErrorKind::FileNameNotAllowedError, |
271 |
| - "Path for creating a directory must contain a parent and child component", |
272 |
| - )), |
273 |
| - } |
274 |
| -} |
275 |
| - |
276 |
| -fn transform_to_ftp_error(error: ApiError) -> Error { |
277 |
| - match error { |
278 |
| - ReqwestError(err) => { |
279 |
| - warn!("Cought reqwest error {}", err); |
280 |
| - Error::new(ErrorKind::LocalError, "Internal Server Error") |
281 |
| - } |
282 |
| - ResponseMalformed(err) => { |
283 |
| - warn!("Filesystemservice error response: {}", err); |
284 |
| - Error::new(ErrorKind::PermanentDirectoryNotAvailable, err) |
285 |
| - } |
286 |
| - } |
287 |
| -} |
288 |
| - |
289 |
| -// IDEA: check if rclone does try to update the root folder |
290 |
| -fn path_contains_rclone_modification_date(path: &Path) -> Option<(NaiveDateTime, PathBuf)> { |
291 |
| - let mut components: Vec<Component> = path.components().collect(); |
292 |
| - |
293 |
| - // needs to be at least / and date<whitespace> |
294 |
| - if components.len() < 2 { |
295 |
| - return None; |
296 |
| - } |
297 |
| - |
298 |
| - // does exist |
299 |
| - let mut timestamp_component = components[1].as_os_str().to_str()?.to_owned(); |
300 |
| - |
301 |
| - #[allow(clippy::unwrap_used)] |
302 |
| - // if root path does not end with whitespace |
303 |
| - if timestamp_component.is_empty() || timestamp_component.pop().unwrap() != ' ' { |
304 |
| - return None; |
305 |
| - } |
306 |
| - |
307 |
| - // the rest of the root folder needs to be in this format |
308 |
| - // yyyymmddhhmmss |
309 |
| - let parsed_time = NaiveDateTime::parse_from_str(×tamp_component, "%Y%m%d%H%M%S").ok()?; |
310 |
| - |
311 |
| - // remove the timestamp component |
312 |
| - components.remove(1); |
313 |
| - |
314 |
| - Some((parsed_time, components.iter().collect())) |
315 |
| -} |
316 |
| - |
317 |
| -#[cfg(test)] |
318 |
| -mod tests { |
319 |
| - use super::path_contains_rclone_modification_date; |
320 |
| - use chrono::NaiveDateTime; |
321 |
| - use std::{path::PathBuf, str::FromStr}; |
322 |
| - |
323 |
| - #[test] |
324 |
| - fn timestamp_parsing_works() { |
325 |
| - let result = NaiveDateTime::parse_from_str("20221003093709", "%Y%m%d%H%M%S").unwrap(); |
326 |
| - let resulting_string = result.to_string(); |
327 |
| - assert_eq!("2022-10-03 09:37:09", resulting_string) |
328 |
| - } |
329 |
| - |
330 |
| - #[test] |
331 |
| - fn path_contains_rclone_modification_date_works() { |
332 |
| - let path = PathBuf::from_str("/20221003093709 /Home/School").unwrap(); |
333 |
| - let option = path_contains_rclone_modification_date(&path); |
334 |
| - |
335 |
| - match option { |
336 |
| - Some(result) => { |
337 |
| - assert_eq!( |
338 |
| - NaiveDateTime::parse_from_str("20221003093709", "%Y%m%d%H%M%S").unwrap(), |
339 |
| - result.0 |
340 |
| - ); |
341 |
| - assert_eq!(PathBuf::from_str("/Home/School").unwrap(), result.1); |
342 |
| - } |
343 |
| - None => panic!("Expected some value here."), |
344 |
| - } |
345 |
| - } |
346 |
| - |
347 |
| - #[test] |
348 |
| - fn path_contains_rclone_modification_date_fails_without_whitespace() { |
349 |
| - let path = PathBuf::from_str("/20221003093709/Home/School").unwrap(); |
350 |
| - let option = path_contains_rclone_modification_date(&path); |
351 |
| - assert!(option.is_none()) |
352 |
| - } |
353 |
| - |
354 |
| - #[test] |
355 |
| - fn path_contains_rclone_modification_date_fails_with_wrong_timestamp_format() { |
356 |
| - let path = PathBuf::from_str("/202210030937 /Home/School").unwrap(); |
357 |
| - let option = path_contains_rclone_modification_date(&path); |
358 |
| - assert!(option.is_none()) |
359 |
| - } |
360 |
| - |
361 |
| - #[test] |
362 |
| - fn path_contains_rclone_modification_date_fails_with_wrong_timestamp() { |
363 |
| - let path = PathBuf::from_str("/20221003093790 /Home/School").unwrap(); |
364 |
| - let option = path_contains_rclone_modification_date(&path); |
365 |
| - assert!(option.is_none()) |
366 |
| - } |
367 |
| -} |
0 commit comments