Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
static_files.rs 7.66 KiB
Newer Older
  • Learn to ignore specific revisions
  • peterrabbit's avatar
    peterrabbit committed
    use crate::app::AppState;
    
    use std::path::{Path, PathBuf};
    
    peterrabbit's avatar
    peterrabbit committed
    pub struct StaticFilesManager {
    
    peterrabbit's avatar
    peterrabbit committed
        pub dir: PathBuf,
        pub index: Vec<String>,
    
    const STATIC_ASSETS_DIRECTORIES: [&'static str; 6] = [
        "images",
        "sounds",
        "videos",
        "docs",
        "source_code",
        "default",
    ];
    
    
    peterrabbit's avatar
    peterrabbit committed
    impl StaticFilesManager {
    
        pub fn new(app_state: &AppState) -> Result<Self, String> {
            match Self::create_dir_if_missing(&app_state.config.storage_dir) {
                Ok(dir) => Ok(StaticFilesManager {
                    index: Vec::new(),
                    dir,
                }),
                Err(msg) => Err(msg),
            }
        }
    
    
        #[cfg(test)]
        pub fn testing_new(test_dir: &PathBuf) -> Result<Self, String> {
            match Self::create_dir_if_missing(test_dir) {
                Ok(dir) => Ok(StaticFilesManager {
                    index: Vec::new(),
                    dir,
                }),
                Err(msg) => Err(msg),
            }
        }
    
    
    peterrabbit's avatar
    peterrabbit committed
        fn create_dir_if_missing(app_dir: &PathBuf) -> Result<PathBuf, String> {
            let static_dir = app_dir.join("static");
    
            if !static_dir.exists() {
                match std::fs::create_dir_all(&static_dir) {
                    Ok(_) => {
    
                        if let Err(err) = Self::create_assets_directories_structure(&static_dir) {
                            return Err(format!("{}", err));
                        };
    
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                        if let Err(err) = Self::copy_default_files(&static_dir) {
    
    peterrabbit's avatar
    peterrabbit committed
                            return Err(format!("{}", err));
                        }
                    }
    
    peterrabbit's avatar
    peterrabbit committed
                    Err(err) => return Err(format!("{}", err)),
                }
            }
    
    
    peterrabbit's avatar
    peterrabbit committed
            Ok(static_dir)
    
        fn create_assets_directories_structure(root: &PathBuf) -> Result<(), std::io::Error> {
            for d in STATIC_ASSETS_DIRECTORIES {
                std::fs::create_dir(root.join(d))?;
            }
    
            Ok(())
        }
    
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
        fn copy_default_files(static_dir: &PathBuf) -> Result<(), String> {
    
    peterrabbit's avatar
    peterrabbit committed
            let local_default_static = std::env::current_dir().unwrap().join("default_static");
            let default_static = static_dir.join("default");
    
            let mut cpy_options = fs_extra::dir::CopyOptions::new();
            cpy_options.content_only = true;
            match fs_extra::dir::copy(local_default_static, default_static, &cpy_options) {
    
    peterrabbit's avatar
    peterrabbit committed
                Err(err) => Err(format!("{}", err)),
    
                Ok(_) => Ok(()),
    
        fn rec_read_dir(&mut self, root: &Path, strip_from: &Path) {
            for entry in root.read_dir().unwrap() {
                if let Ok(entry) = entry {
                    if entry.path().is_dir() {
                        self.rec_read_dir(&entry.path(), strip_from);
                    } else {
    
                        self.push_path(&entry.path().strip_prefix(strip_from).unwrap());
    
        fn validate_path(&self, path: &Path) -> bool {
            self.dir.join(self.clean_relative_path(path)).exists()
        }
    
        fn clean_relative_path(&self, path: &Path) -> PathBuf {
            match path.starts_with("/") {
                true => path.strip_prefix("/").unwrap().to_path_buf(),
                false => path.to_path_buf(),
            }
        }
    
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
        pub fn push_path(&mut self, path: &Path) -> Vec<PathBuf> {
    
            if self.validate_path(path) {
                self.index
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                    .push(self.clean_relative_path(path).to_str().unwrap().to_owned());
    
                vec![path.to_path_buf()]
            } else {
                println!(
                    "[WARNING] Error building static file index. The file {:?} doesn't exist and will be removed from the index.",
                    self.dir.join(self.clean_relative_path(path)),
                );
                Vec::new()
            }
    
        pub fn add_pathes(&mut self, pathes: &Vec<String>) -> Vec<PathBuf> {
            let mut added: Vec<PathBuf> = Vec::new();
            for pth in pathes.iter() {
                let p = self.push_path(Path::new(pth));
                added.extend(p.iter().map(|pb| pb.clone()));
            }
            added
    
        }
    
        pub fn build(&mut self) -> Self {
    
            self.index = Vec::new();
            self.rec_read_dir(&self.dir.clone(), &self.dir.clone());
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
    
        pub fn remove_path(&mut self, strpath: String) {
            println!("REMOVE {}", strpath);
            println!("current Index {:#?}", self.index);
            self.index = self
                .index
                .iter()
                .filter(|url| !strpath.eq(*url))
                .map(|s| s.to_owned())
                .collect();
            println!("Updated Index {:#?}", self.index);
        }
    
        pub fn get_index(&self) -> Vec<String> {
            self.index.clone()
        }
    
    
    #[cfg(test)]
    mod test_static_files_manager {
        use super::*;
    
        fn create_test_dir() -> PathBuf {
            let pth = PathBuf::from("./test");
            let _ = std::fs::create_dir(&pth);
            pth
        }
    
        fn remove_test_dir(pth: &PathBuf) {
            let _ = std::fs::remove_dir_all(pth);
        }
    
        #[test]
        fn test_directory_structure() {
            let test_dir = create_test_dir();
            let _manager = StaticFilesManager::testing_new(&test_dir).unwrap();
    
            for d in STATIC_ASSETS_DIRECTORIES {
                let p = test_dir.join("static").join(d);
                let exists = p.exists();
                assert!(
                    exists,
                    "{} doesn't exist\n{:?}",
                    p.display(),
                    remove_test_dir(&test_dir)
                );
            }
    
            remove_test_dir(&test_dir);
        }
    
        #[test]
        fn test_indexation() {
            let test_dir = create_test_dir();
            let mut manager = StaticFilesManager::testing_new(&test_dir).unwrap();
            let file_pth = test_dir.join("static").join("docs").join("testing.txt");
            std::fs::File::create(&file_pth).unwrap();
            manager = manager.build();
    
            assert!(
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                manager.index.contains(&"docs/testing.txt".to_string()),
    
                "Index doesn't contain path /docs/testing.txt\n{:?}",
                remove_test_dir(&test_dir)
            );
    
            remove_test_dir(&test_dir);
        }
    
        #[test]
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
        fn test_pushd_andremove_path() {
    
            let test_dir = create_test_dir();
            let mut manager = StaticFilesManager::testing_new(&test_dir).unwrap().build();
            let file_pth = test_dir.join("static").join("docs").join("testing.txt");
            std::fs::File::create(&file_pth).unwrap();
            let indexed_path = Path::new("docs/testing.txt");
            let added = manager.push_path(&indexed_path);
    
            assert_eq!(
                added,
                vec![PathBuf::from("docs/testing.txt")],
                "Path was not added\n{:?}",
                remove_test_dir(&test_dir)
            );
    
            assert!(
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                manager.index.contains(&"docs/testing.txt".to_string()),
    
                "Index doesn't contain path /docs/testing.txt\n{:?}",
                remove_test_dir(&test_dir)
            );
    
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
            manager.remove_path("docs/testing.txt".to_string());
    
            assert!(
                !manager.index.contains(&"docs/testing.txt".to_string()),
                "Path docs/testing.txt should have been removed\n{:?}",
                remove_test_dir(&test_dir)
            );
    
    
            remove_test_dir(&test_dir);
        }
    
        #[test]
        fn test_push_unexisting_path() {
            let test_dir = create_test_dir();
            let mut manager = StaticFilesManager::testing_new(&test_dir).unwrap().build();
            let indexed_path = Path::new("images/unexisting.png");
            let added = manager.push_path(&indexed_path);
    
            assert_eq!(
                added.len(),
                0,
                "No path should have been added\n{:?}",
                remove_test_dir(&test_dir)
            );
    
            assert!(
    
    Pierre Jarriges's avatar
    Pierre Jarriges committed
                !manager.index.contains(&"images/unexisting.png".to_string()),
    
                "Index shouldn't container unexisting path\n{:?}",
                remove_test_dir(&test_dir)
            );
    
            remove_test_dir(&test_dir);
        }
    }