diff --git a/filed/config/filed.toml.example b/filed/config/filed.toml.example index dd3d161..9ab705d 100644 --- a/filed/config/filed.toml.example +++ b/filed/config/filed.toml.example @@ -84,3 +84,7 @@ sudo_delete=false # Whether /api/upload is enabled # It is not recommended to enable it if API key auth is not enabled upload=false + +# Whether curlapi is enabled +# curl {url}/curlapi/help for more info +curlapi=true diff --git a/filed/src/config/types.rs b/filed/src/config/types.rs index 878230d..050a1d2 100644 --- a/filed/src/config/types.rs +++ b/filed/src/config/types.rs @@ -112,6 +112,10 @@ pub struct APISettings { /// Whether /api/upload is enabled #[serde(default)] pub upload: bool, + + /// Whether curlapi is enabled + #[serde(default)] + pub curlapi: bool } impl Default for APISettings { @@ -123,7 +127,8 @@ impl Default for APISettings { get_all_own_only: true, delete: false, sudo_delete: false, - upload: false + upload: false, + curlapi: true } } } diff --git a/filed/src/web/curlapi.rs b/filed/src/web/curlapi.rs index 35fa226..8538802 100644 --- a/filed/src/web/curlapi.rs +++ b/filed/src/web/curlapi.rs @@ -3,7 +3,9 @@ use warp::{Filter, reply::Reply, reject::Rejection}; use super::state::SharedState; mod upload; +mod help; pub fn get_routes(state: SharedState) -> impl Filter + Clone { - upload::get_routes(state) + upload::get_routes(state.clone()) + .or(help::get_routes(state)) } \ No newline at end of file diff --git a/filed/src/web/curlapi/help.rs b/filed/src/web/curlapi/help.rs new file mode 100644 index 0000000..0480b8b --- /dev/null +++ b/filed/src/web/curlapi/help.rs @@ -0,0 +1,71 @@ +use warp::{Filter, reply::Reply, reject::Rejection}; + +use crate::web::state::SharedState; + +pub async fn help(state: SharedState) -> Result { + + let brand = format!( + "{} \x1b[1m{}\x1b[0m {}", + state.config.brand.instance_emoji, + state.config.brand.instance_name, + { + if state.config.brand.instance_name != "blek! File" { + "\n\x1b[90mPowered by blek! File\x1b[0m" + } else { "" } + } + ); + + let mut warns: String = String::new(); + if ! state.config.api.curlapi { + warns += "\x1b[1;31mWarning: curl API is disabled on this instance.\nYou can use the web UI to upload files.\x1b[0m\n\n" + } + if ! state.config.files.allow_uploads { + warns += { + format!( + "\x1b[1;31mWarning: all uploads are disabled on this instance{}\x1b[0m", + { + if let Some(reason) = state.config.files.upload_disable_reason { + format!(" for this reason:\n\"{}\"", reason) + } else { ".".to_string() } + } + ).as_str() + } + } + + let instance = state.env.instanceurl; + let help = +format!( +"To upload a new file, you can POST it like this: + \x1b[32mcurl\x1b[0m \x1b[33m-X POST\x1b[0m \x1b[34m{instance}/curlapi/upload\x1b[0m \x1b[33m-F'file=@file.txt'\x1b[0m \x1b[33m-F'tos_consent=on'\x1b[0m +You can also add a password: + \x1b[32mcurl\x1b[0m \x1b[33m-X POST\x1b[0m \x1b[34m{instance}/curlapi/upload\x1b[0m \x1b[33m-F'file=@file.txt'\x1b[0m \x1b[33m-F'filename=uwu'\x1b[0m \x1b[33m-F'tos_consent=on'\x1b[0m \x1b[33m-F'named=on'\x1b[0m +The `named=on` switch is neede because this API is basically +the HTML used at the regular web UI form wrapped into this URL + +\x1b[1;32mIMPORTANT:\x1b[0m Read the terms of service \x1b[1mbefore\x1b[0m uploading the file! +The ToS can be found here: \x1b[34m{instance}/tos\x1b[0m . + +{warns} +" +); + + Ok(format!(" + \x1b[31m┓ ╻\x1b[0m \x1b[35m┏┓•┓ \x1b[0m + \x1b[32m┣┓┃\x1b[0m \x1b[95m┣ ┓┃┏┓\x1b[0m + \x1b[34m┗┛•\x1b[0m \x1b[35m┻ ┗┗┗━\x1b[0m + +{brand} + +{help} +").into()) +} + +pub fn get_routes(state: SharedState) -> impl Filter + Clone { + warp::any() + .and(warp::path!("curlapi" / "help")) + .and( + warp::any() + .map(move || state.clone()) + ) + .and_then(help) +} \ No newline at end of file diff --git a/filed/src/web/curlapi/upload.rs b/filed/src/web/curlapi/upload.rs index a15aa07..fa85a1f 100644 --- a/filed/src/web/curlapi/upload.rs +++ b/filed/src/web/curlapi/upload.rs @@ -111,7 +111,7 @@ pub async fn upload(form: FormData, ip: Option, state: SharedState) -> R } pub fn get_routes(state: SharedState) -> impl Filter + Clone { - warp::any() + warp::post() .and(warp::path!("curlapi" / "upload")) .and(warp::multipart::form()) .and(real_ip(vec![state.env.proxy_addr]))