Compare commits
No commits in common. "589ff7b0400c55aacb7cd7018668eef3be6a0ebe" and "36bda058256f79a46703aa26428ce4e3b277abfa" have entirely different histories.
589ff7b040
...
36bda05825
|
@ -74,7 +74,7 @@ paths:
|
||||||
example: {}
|
example: {}
|
||||||
401:
|
401:
|
||||||
description: |-
|
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.
|
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.
|
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:
|
fid:
|
||||||
type: string
|
type: string
|
||||||
example: ID or name of the file. It is the NAME in file.blek.codes/uploads/NAME
|
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:
|
/api/files/upload:
|
||||||
post:
|
post:
|
||||||
summary: Upload a file
|
summary: Upload a file
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use redis::{Client, Commands, AsyncCommands, Connection};
|
use redis::{Client, Commands, AsyncCommands, Connection};
|
||||||
|
use tokio::task::JoinSet;
|
||||||
|
|
||||||
use crate::env::Env;
|
use crate::env::Env;
|
||||||
|
|
||||||
|
|
|
@ -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(
|
warp::reply::with_status(
|
||||||
json(&ErrorMessage::new(Error::APIFunctionDisabled)),
|
json(&ErrorMessage::new(Error::APIFunctionDisabled)),
|
||||||
status
|
StatusCode::SERVICE_UNAVAILABLE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,57 +1,26 @@
|
||||||
use std::{collections::HashMap, net::IpAddr};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde_json::json;
|
use warp::{reply::{Reply, json}, reject::Rejection, Filter, http::StatusCode};
|
||||||
use warp::{reply::{Reply, json, with_status}, reject::Rejection, Filter, http::StatusCode};
|
|
||||||
use serde::{Serialize, Deserialize};
|
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};
|
use super::{function_disabled_err, check_api_enabled};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct DeleteFunctionPayload {
|
pub struct DeleteFunctionPayload {
|
||||||
pub fid: String,
|
pub fid: String
|
||||||
pub api_key: Option<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) {
|
if let Err(res) = check_api_enabled(&state) {
|
||||||
return Ok(Box::new(res));
|
return Ok(Box::new(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.config.api.delete) || (!state.config.api.enabled) {
|
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 id = body.fid;
|
||||||
let mut file = state.file_mgr.find_by_hash(id.clone())
|
let mut file = state.file_mgr.find_by_hash(id.clone())
|
||||||
.map_err(|x| HttpReject::StringError(x.to_string()))?;
|
.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()))?;
|
.map_err(|x| HttpReject::StringError(x.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let None = file.clone() {
|
if let None = file {
|
||||||
return Ok(
|
return Ok(
|
||||||
Box::new(
|
Box::new(
|
||||||
warp::reply::with_status(
|
warp::reply::with_status(
|
||||||
|
@ -77,46 +46,12 @@ pub async fn delete(state: SharedState, body: DeleteFunctionPayload, ip: Option<
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let file: File = file.unwrap();
|
Ok(Box::new(json(&HashMap::<(), ()>::new())))
|
||||||
|
|
||||||
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!({}))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_f(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
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")
|
warp::path!("api" / "files" / "delete")
|
||||||
.map(move || state.clone())
|
.map(move || state.clone())
|
||||||
.and(warp::body::json())
|
.and(warp::body::json())
|
||||||
.and(real_ip(vec![proxy_ip]))
|
|
||||||
.and_then(delete)
|
.and_then(delete)
|
||||||
}
|
}
|
|
@ -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) {
|
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 =
|
let found =
|
||||||
|
@ -48,6 +48,7 @@ pub async fn get_all(state: SharedState, ip: Option<IpAddr>) -> Result<Box<dyn R
|
||||||
|x| {
|
|x| {
|
||||||
if let Some(owner) = x.uploader_ip {
|
if let Some(owner) = x.uploader_ip {
|
||||||
if let Some(caller) = ip {
|
if let Some(caller) = ip {
|
||||||
|
println!("{owner} {caller}");
|
||||||
return owner == caller
|
return owner == caller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue