Compare commits

..

No commits in common. "589ff7b0400c55aacb7cd7018668eef3be6a0ebe" and "36bda058256f79a46703aa26428ce4e3b277abfa" have entirely different histories.

5 changed files with 14 additions and 80 deletions

View File

@ -74,7 +74,7 @@ paths:
example: {}
401:
description: |-
This error code is returned if one of these conditions are met:
This error code is returned if one of the two conditions are met:
1. The instance does not allow deleting files via API.
2. The file has been uploaded from another IP, which is not this one, and the API was not authorized via an API key.
@ -90,9 +90,6 @@ paths:
fid:
type: string
example: ID or name of the file. It is the NAME in file.blek.codes/uploads/NAME
api_key:
type: string
example: '123'
/api/files/upload:
post:
summary: Upload a file

View File

@ -2,6 +2,7 @@
use std::error::Error;
use redis::{Client, Commands, AsyncCommands, Connection};
use tokio::task::JoinSet;
use crate::env::Env;

View File

@ -49,10 +49,10 @@ fn check_api_pass(state: &SharedState, key: String) -> Result<(), WithStatus<Jso
}
}
fn function_disabled_err(status: StatusCode) -> WithStatus<Json> {
fn function_disabled_err() -> WithStatus<Json> {
warp::reply::with_status(
json(&ErrorMessage::new(Error::APIFunctionDisabled)),
status
StatusCode::SERVICE_UNAVAILABLE
)
}

View File

@ -1,57 +1,26 @@
use std::{collections::HashMap, net::IpAddr};
use std::collections::HashMap;
use serde_json::json;
use warp::{reply::{Reply, json, with_status}, reject::Rejection, Filter, http::StatusCode};
use warp::{reply::{Reply, json}, reject::Rejection, Filter, http::StatusCode};
use serde::{Serialize, Deserialize};
use warp_real_ip::real_ip;
use crate::{web::{state::SharedState, rejection::HttpReject, api::types::{ErrorMessage, Error}}, files::File};
use crate::web::{state::SharedState, rejection::HttpReject, api::types::{ErrorMessage, Error}};
use super::{function_disabled_err, check_api_enabled};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DeleteFunctionPayload {
pub fid: String,
pub api_key: Option<String>
pub fid: String
}
pub async fn delete(state: SharedState, body: DeleteFunctionPayload, ip: Option<IpAddr>) -> Result<Box<dyn Reply>, Rejection> {
pub async fn delete(state: SharedState, body: DeleteFunctionPayload) -> Result<Box<dyn Reply>, Rejection> {
if let Err(res) = check_api_enabled(&state) {
return Ok(Box::new(res));
}
if (!state.config.api.delete) || (!state.config.api.enabled) {
return Ok(Box::new(function_disabled_err(StatusCode::UNAUTHORIZED)))
return Ok(Box::new(function_disabled_err()))
}
let mut sudo_authorized = false;
let mut blocked = false;
if let Some(keys) = state.config.api.apikeys.clone() {
if let Some(key) = body.api_key {
if keys.contains(&key) {
sudo_authorized = true;
blocked = false;
} else {
sudo_authorized = false;
blocked = true;
}
} else {
sudo_authorized = false;
blocked = true
}
}
if ! sudo_authorized {
if ip.is_none() { // need the ip if sudo is not authorized
blocked = true // to check if the file is the own file
}
}
let ip = ip.unwrap();
let id = body.fid;
let mut file = state.file_mgr.find_by_hash(id.clone())
.map_err(|x| HttpReject::StringError(x.to_string()))?;
@ -61,7 +30,7 @@ pub async fn delete(state: SharedState, body: DeleteFunctionPayload, ip: Option<
.map_err(|x| HttpReject::StringError(x.to_string()))?;
}
if let None = file.clone() {
if let None = file {
return Ok(
Box::new(
warp::reply::with_status(
@ -76,47 +45,13 @@ pub async fn delete(state: SharedState, body: DeleteFunctionPayload, ip: Option<
)
)
}
let file: File = file.unwrap();
if let Some(uploader) = file.uploader_ip {
if uploader != ip && (!sudo_authorized) {
blocked = true;
}
} else {
blocked = true;
}
if blocked {
return Ok(
Box::new(
with_status(
json(
&ErrorMessage {
error: Error::APIPasswordDenied,
details: Some(
"Request has been denied for one of the following reasons: password auth did not pass, file was uploaded by someone else, the instance does not allow deleting files via the API".into()
)
}
),
StatusCode::UNAUTHORIZED
)
)
)
}
file.delete(state).await;
Ok(Box::new(json(&json!({}))))
Ok(Box::new(json(&HashMap::<(), ()>::new())))
}
pub fn delete_f(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
let proxy_ip = state.env.proxy_addr;
warp::path!("api" / "files" / "delete")
.map(move || state.clone())
.and(warp::body::json())
.and(real_ip(vec![proxy_ip]))
.and_then(delete)
}

View File

@ -13,7 +13,7 @@ pub async fn get_all(state: SharedState, ip: Option<IpAddr>) -> Result<Box<dyn R
}
if (!state.config.api.get_all) || (!state.config.api.enabled) {
return Ok(Box::new(function_disabled_err(StatusCode::UNAUTHORIZED)))
return Ok(Box::new(function_disabled_err()))
}
let found =
@ -48,6 +48,7 @@ pub async fn get_all(state: SharedState, ip: Option<IpAddr>) -> Result<Box<dyn R
|x| {
if let Some(owner) = x.uploader_ip {
if let Some(caller) = ip {
println!("{owner} {caller}");
return owner == caller
}
}