feat: file repo

This commit is contained in:
Gabor Körber 2024-05-12 13:26:21 +02:00
parent 20fc177280
commit 8fa6886e77
5 changed files with 56 additions and 17 deletions

9
Cargo.lock generated
View File

@ -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",

View File

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

View File

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

View File

@ -1,3 +1,4 @@
pub mod empty_repository;
pub mod static_repository;
pub mod user_repository;
pub mod file_repository;

View File

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