feat: file repo
This commit is contained in:
		
							parent
							
								
									20fc177280
								
							
						
					
					
						commit
						8fa6886e77
					
				
							
								
								
									
										9
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -651,15 +651,17 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "chrono"
 | 
			
		||||
version = "0.4.31"
 | 
			
		||||
version = "0.4.38"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
 | 
			
		||||
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "android-tzdata",
 | 
			
		||||
 "iana-time-zone",
 | 
			
		||||
 "js-sys",
 | 
			
		||||
 "num-traits",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "windows-targets 0.48.5",
 | 
			
		||||
 "wasm-bindgen",
 | 
			
		||||
 "windows-targets 0.52.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -1756,6 +1758,7 @@ dependencies = [
 | 
			
		||||
 "async-trait",
 | 
			
		||||
 "axum 0.7.4",
 | 
			
		||||
 "barrel",
 | 
			
		||||
 "chrono",
 | 
			
		||||
 "dotenvy",
 | 
			
		||||
 "dunce",
 | 
			
		||||
 "entity",
 | 
			
		||||
 | 
			
		||||
@ -53,3 +53,4 @@ slug = "0.1.5"
 | 
			
		||||
async-trait = "0.1.77"
 | 
			
		||||
tracing = "0.1.40"
 | 
			
		||||
tower-http = { version = "0.5.1", features = ["trace"] }
 | 
			
		||||
chrono = "0.4.38"
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,19 @@
 | 
			
		||||
use crate::admin::domain::*;
 | 
			
		||||
use async_trait::async_trait;
 | 
			
		||||
use rear::admin::state::AdminRegistry;
 | 
			
		||||
use serde_json::Value;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
struct FileRepository {
 | 
			
		||||
    directory_path: String,
 | 
			
		||||
    directory_path: PathBuf,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FileRepository {
 | 
			
		||||
    pub fn new(folder: String) -> Self {
 | 
			
		||||
    pub fn new(from_path: &str) -> Self {
 | 
			
		||||
        
 | 
			
		||||
        let proper_path = file_operations::get_proper_path(from_path);
 | 
			
		||||
        FileRepository {
 | 
			
		||||
            directory_path: folder,
 | 
			
		||||
            directory_path: proper_path,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -36,8 +40,15 @@ impl AdminRepository for FileRepository {
 | 
			
		||||
 | 
			
		||||
    // GET on item collection.
 | 
			
		||||
    async fn list(&self, model: &RepositoryContext) -> RepositoryList {
 | 
			
		||||
        if let Some(file_data) = file_operations::directory_info(&self.directory_path) {
 | 
			
		||||
            return RepositoryList::List(file_data);
 | 
			
		||||
        if let Ok(file_data) = file_operations::directory_info(&self.directory_path) {
 | 
			
		||||
            let items: Vec<RepositoryItem> = file_data.into_iter().map(|fields| {
 | 
			
		||||
                RepositoryItem {
 | 
			
		||||
                    fields,
 | 
			
		||||
                    detail_url: None, // TODO: change the return type of directory_info into a struct, so we can access key.
 | 
			
		||||
                    change_url: None,
 | 
			
		||||
                }
 | 
			
		||||
            }).collect();
 | 
			
		||||
            return RepositoryList::List { values: items };
 | 
			
		||||
        }
 | 
			
		||||
        RepositoryList::Empty
 | 
			
		||||
    }
 | 
			
		||||
@ -82,12 +93,12 @@ impl AdminRepository for FileRepository {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn register(registry: &mut AdminRegistry, db: DatabaseConnection) {
 | 
			
		||||
    let app_key = registry.register_app("Static");
 | 
			
		||||
    let repo = FileRepository::new(db);
 | 
			
		||||
pub fn register(registry: &mut AdminRegistry, path: &str) {
 | 
			
		||||
    let app_key = registry.register_app("Files");
 | 
			
		||||
    let repo = FileRepository::new(path);
 | 
			
		||||
    let model_config = AdminModelConfig {
 | 
			
		||||
        app_key: app_key,
 | 
			
		||||
        name: "User".to_owned(),
 | 
			
		||||
        name: "Files".to_owned(),
 | 
			
		||||
    };
 | 
			
		||||
    let model_result = registry.register_model(model_config, repo);
 | 
			
		||||
    match model_result {
 | 
			
		||||
@ -100,6 +111,15 @@ mod file_operations {
 | 
			
		||||
    use serde_json::{json, Value};
 | 
			
		||||
    use std::fs;
 | 
			
		||||
    use std::path::Path;
 | 
			
		||||
    use std::env;
 | 
			
		||||
    use std::path::PathBuf;
 | 
			
		||||
    use std::time::SystemTime;
 | 
			
		||||
    use chrono::{DateTime, Utc, TimeZone};
 | 
			
		||||
 | 
			
		||||
    fn system_time_to_iso_string(system_time: SystemTime) -> String {
 | 
			
		||||
        let datetime: DateTime<Utc> = system_time.into();
 | 
			
		||||
        datetime.to_rfc3339()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_metadata_as_json(path: &Path) -> Result<Value, Box<dyn std::error::Error>> {
 | 
			
		||||
        let metadata = fs::metadata(path)?;
 | 
			
		||||
@ -118,8 +138,8 @@ mod file_operations {
 | 
			
		||||
        let is_symlink = file_type.is_symlink();
 | 
			
		||||
 | 
			
		||||
        // Format times as strings if they exist
 | 
			
		||||
        let modified_time_str = modified_time.map(|t| t.to_string());
 | 
			
		||||
        let created_time_str = created_time.map(|t| t.to_string());
 | 
			
		||||
        let modified_time_str = modified_time.map(|t| system_time_to_iso_string(t));
 | 
			
		||||
        let created_time_str = created_time.map(|t| system_time_to_iso_string(t));
 | 
			
		||||
 | 
			
		||||
        Ok(json!({
 | 
			
		||||
            "path": path.display().to_string(),
 | 
			
		||||
@ -132,12 +152,12 @@ mod file_operations {
 | 
			
		||||
        }))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn file_info(file_path: &str) -> Result<Value, Box<dyn std::error::Error>> {
 | 
			
		||||
        let path = Path::new(file_path);
 | 
			
		||||
    pub fn file_info(file_path: &PathBuf) -> Result<Value, Box<dyn std::error::Error>> {
 | 
			
		||||
        let path = file_path.as_path();
 | 
			
		||||
        get_metadata_as_json(path)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn directory_info(directory_path: &str) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
 | 
			
		||||
    pub fn directory_info(directory_path: &PathBuf) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
 | 
			
		||||
        let entries = fs::read_dir(directory_path)?;
 | 
			
		||||
        let mut results = Vec::new();
 | 
			
		||||
 | 
			
		||||
@ -151,4 +171,16 @@ mod file_operations {
 | 
			
		||||
 | 
			
		||||
        Ok(results)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_proper_path(some_path: &str) -> PathBuf {
 | 
			
		||||
        let path = Path::new(some_path);
 | 
			
		||||
        if path.is_absolute() {
 | 
			
		||||
            return path.to_path_buf();
 | 
			
		||||
        } else {
 | 
			
		||||
            let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into());
 | 
			
		||||
            let template_path = PathBuf::from(manifest_dir).join(path);
 | 
			
		||||
            return template_path;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
pub mod empty_repository;
 | 
			
		||||
pub mod static_repository;
 | 
			
		||||
pub mod user_repository;
 | 
			
		||||
pub mod file_repository;
 | 
			
		||||
@ -7,6 +7,7 @@ mod state;
 | 
			
		||||
use crate::state::AppState;
 | 
			
		||||
use admin_examples::static_repository;
 | 
			
		||||
use admin_examples::user_repository;
 | 
			
		||||
use admin_examples::file_repository;
 | 
			
		||||
use axum::{
 | 
			
		||||
    body::Bytes,
 | 
			
		||||
    extract::MatchedPath,
 | 
			
		||||
@ -53,6 +54,7 @@ async fn main() {
 | 
			
		||||
    // Register Admin Apps
 | 
			
		||||
    static_repository::register(&mut admin);
 | 
			
		||||
    user_repository::register(&mut admin, db_connection);
 | 
			
		||||
    file_repository::register(&mut admin, "static/admin");
 | 
			
		||||
 | 
			
		||||
    // Create global Application State.
 | 
			
		||||
    let state: AppState = AppState {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user