resource mechanism

This commit is contained in:
blek 2023-11-04 14:07:31 +10:00
parent 11543af683
commit 56cf9061f0
Signed by: blek
GPG Key ID: 14546221E3595D0C
6 changed files with 141 additions and 4 deletions

41
filed/Cargo.lock generated
View File

@ -37,6 +37,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "android-tzdata" name = "android-tzdata"
version = "0.1.1" version = "0.1.1"
@ -375,6 +384,7 @@ dependencies = [
"num", "num",
"rand", "rand",
"redis", "redis",
"regex",
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2",
@ -941,7 +951,7 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ec3b11d443640ec35165ee8f6f0559f1c6f41878d70330fe9187012b5935f02" checksum = "9ec3b11d443640ec35165ee8f6f0559f1c6f41878d70330fe9187012b5935f02"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick 0.7.20",
"bumpalo", "bumpalo",
"hashbrown 0.13.2", "hashbrown 0.13.2",
"lazy_static", "lazy_static",
@ -1078,6 +1088,35 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick 1.1.2",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick 1.1.2",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]] [[package]]
name = "rfc7239" name = "rfc7239"
version = "0.1.0" version = "0.1.0"

View File

@ -19,6 +19,7 @@ log = "0.4.20"
num = { version = "0.4.1", features = ["serde"] } num = { version = "0.4.1", features = ["serde"] }
rand = "0.8.5" rand = "0.8.5"
redis = { version = "0.23.3", features = ["tokio", "tokio-comp"] } redis = { version = "0.23.3", features = ["tokio", "tokio-comp"] }
regex = "1.10.2"
serde = { version = "1.0.188", features = ["derive"] } serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"
sha2 = "0.10.8" sha2 = "0.10.8"

View File

@ -1 +1,2 @@
pub mod types; pub mod types;
pub mod resource;

View File

@ -0,0 +1 @@
pub mod types;

View File

@ -0,0 +1,80 @@
use regex::Regex;
use serde::{Serialize, Deserialize};
use std::{error::Error, fs, collections::HashMap, path::Path};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceCollection(HashMap<String, Resource>);
impl ResourceCollection {
pub fn validate(self: &Self) -> Result<(), String> {
for (name, resource) in self.0.iter() {
resource.validate(Some(name.clone()))?;
}
Ok(())
}
pub fn init(self: &mut Self) -> Result<(), String> {
for (name, resource) in self.0.iter_mut() {
resource.init(Some(name.clone()))?;
}
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Resource {
pub path: String,
pub mime: String,
cached_data: Option<Vec<u8>>
}
impl Resource {
pub fn init(self: &mut Self, name: Option<String>) -> Result<(), String> {
if self.cached_data.is_none() {
self.read_to_cache().map_err(|x|
if let Some(name) = name {
format!("Error while initalizing resource {name}: {:?}", x)
} else {
format!("Error while initalizing unknown resource: {:?}", x)
}
)?
}
Ok(())
}
pub fn validate(self: &Self, name: Option<String>) -> Result<(), String> {
// dont catch this panic
let re = Regex::new(r"^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+[0-9a-z_]$").unwrap();
if let Some(name) = name.clone() {
if ! re.is_match(name.as_str()) {
return Err(format!("Invalid resource name: {name}"));
}
}
let path = Path::new(&self.path);
if ! path.is_file() {
if let Some(name) = name {
return Err(format!("Resource {name} is not a file!"));
} else {
return Err(format!("A resource with path {} is not a file!", self.path));
}
}
Ok(())
}
fn read_to_cache(self: &mut Self) -> Result<(), Box<dyn Error>> {
let data = fs::read(self.path.clone())?;
self.cached_data = Some(data);
Ok(())
}
pub fn get(self: &mut Self) -> Result<Vec<u8>, Box<dyn Error>> {
if let Some(cached) = self.cached_data.clone() {
Ok(cached)
} else {
Ok(fs::read(self.path.clone())?)
}
}
}

View File

@ -3,6 +3,8 @@ use std::{error::Error, fs, path::Path};
use crate::env::Env; use crate::env::Env;
use super::resource;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FilesPolicy { pub struct FilesPolicy {
/// Whether the uploads are enabled /// Whether the uploads are enabled
@ -167,7 +169,8 @@ impl APISettings {
pub struct Config { pub struct Config {
pub files: FilesPolicy, pub files: FilesPolicy,
pub brand: Branding, pub brand: Branding,
pub api: APISettings pub api: APISettings,
pub resources: Option<resource::types::ResourceCollection>
} }
impl Config { impl Config {
@ -176,14 +179,26 @@ impl Config {
self.files.validate()?; self.files.validate()?;
self.brand.validate()?; self.brand.validate()?;
self.api .validate()?; self.api .validate()?;
if let Some(resources) = self.resources.clone() {
resources.validate()?;
}
Ok(()) Ok(())
} }
pub fn init(self: &mut Self) -> Result<(), String> {
if let Some(ref mut resources) = self.resources {
resources.init()?;
}
Ok(())
}
pub fn load(env: Env) -> Result<Config, Box<dyn Error>> { pub fn load(env: Env) -> Result<Config, Box<dyn Error>> {
let raw = fs::read_to_string(env.confpath.clone())?; let raw = fs::read_to_string(env.confpath.clone())?;
let conf: Config = toml::from_str(&raw)?; let mut conf: Config = toml::from_str(&raw)?;
conf.validate()?; conf.validate()?;
conf.init()?;
Ok(conf) Ok(conf)
} }
} }