1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-08-11 17:50:59 +00:00

feat(media): deep hashed directory structure

This commit is contained in:
Matthias Ahouansou 2025-03-23 17:23:57 +00:00
parent 66a14ac802
commit 19d0ea408c
No known key found for this signature in database
5 changed files with 173 additions and 35 deletions

View file

@ -2,6 +2,7 @@ use std::{
collections::BTreeMap,
fmt,
net::{IpAddr, Ipv4Addr},
num::NonZeroU8,
path::PathBuf,
};
@ -10,10 +11,13 @@ use serde::{de::IgnoredAny, Deserialize};
use tracing::warn;
use url::Url;
mod proxy;
use crate::Error;
mod proxy;
use self::proxy::ProxyConfig;
const SHA256_HEX_LENGTH: u8 = 64;
#[derive(Deserialize)]
pub struct IncompleteConfig {
#[serde(default = "default_address")]
@ -218,7 +222,10 @@ impl From<IncompleteConfig> for Config {
};
let media = match media {
IncompleteMediaConfig::FileSystem { path } => MediaConfig::FileSystem {
IncompleteMediaConfig::FileSystem {
path,
directory_structure,
} => MediaConfig::FileSystem {
path: path.unwrap_or_else(|| {
// We do this as we don't know if the path has a trailing slash, or even if the
// path separator is a forward or backward slash
@ -229,6 +236,7 @@ impl From<IncompleteConfig> for Config {
.into_string()
.expect("Both inputs are valid UTF-8")
}),
directory_structure,
},
};
@ -309,21 +317,85 @@ pub struct WellKnownConfig {
pub server: OwnedServerName,
}
#[derive(Clone, Debug, Deserialize)]
#[derive(Deserialize)]
#[serde(tag = "backend", rename_all = "lowercase")]
pub enum IncompleteMediaConfig {
FileSystem { path: Option<String> },
FileSystem {
path: Option<String>,
#[serde(default)]
directory_structure: DirectoryStructure,
},
}
impl Default for IncompleteMediaConfig {
fn default() -> Self {
Self::FileSystem { path: None }
Self::FileSystem {
path: None,
directory_structure: DirectoryStructure::default(),
}
}
}
#[derive(Debug, Clone)]
pub enum MediaConfig {
FileSystem { path: String },
FileSystem {
path: String,
directory_structure: DirectoryStructure,
},
}
#[derive(Debug, Clone, Deserialize)]
// See https://github.com/serde-rs/serde/issues/642#issuecomment-525432907
#[serde(try_from = "ShadowDirectoryStructure", untagged)]
pub enum DirectoryStructure {
// We do this enum instead of Option<DirectoryStructure>, so that we can have the structure be
// deep by default, while still providing a away for it to be flat (by creating an empty table)
//
// e.g.:
// ```toml
// [global.media.directory_structure]
// ```
Flat,
Deep { length: NonZeroU8, depth: NonZeroU8 },
}
impl Default for DirectoryStructure {
fn default() -> Self {
Self::Deep {
length: NonZeroU8::new(2).expect("2 is not 0"),
depth: NonZeroU8::new(2).expect("2 is not 0"),
}
}
}
#[derive(Deserialize)]
#[serde(untagged)]
enum ShadowDirectoryStructure {
Flat {},
Deep { length: NonZeroU8, depth: NonZeroU8 },
}
impl TryFrom<ShadowDirectoryStructure> for DirectoryStructure {
type Error = Error;
fn try_from(value: ShadowDirectoryStructure) -> Result<Self, Self::Error> {
match value {
ShadowDirectoryStructure::Flat {} => Ok(Self::Flat),
ShadowDirectoryStructure::Deep { length, depth } => {
if length
.get()
.checked_mul(depth.get())
.map(|product| product < SHA256_HEX_LENGTH)
// If an overflow occurs, it definitely isn't less than SHA256_HEX_LENGTH
.unwrap_or(false)
{
Ok(Self::Deep { length, depth })
} else {
Err(Error::bad_config("The media directory structure depth multiplied by the depth is equal to or greater than a sha256 hex hash, please reduce at least one of the two so that their product is less than 64"))
}
}
}
}
}
const DEPRECATED_KEYS: &[&str] = &[