@@ -30,6 +30,7 @@ use std::{net::SocketAddr, path::PathBuf};
3030use tokio:: io:: AsyncSeekExt ;
3131use tokio_util:: io:: ReaderStream ;
3232use tower:: ServiceBuilder ;
33+ use toml:: Table ;
3334
3435
3536#[ derive( Parser , Debug ) ]
@@ -270,6 +271,44 @@ fn heuristic_filetype(filename: String) -> String {
270271 }
271272}
272273
274+ /*
275+ Example config.toml section:
276+
277+ [users]
278+ [users.alice]
279+ prefixes = ["/alice"]
280+ [users.bob]
281+ prefixes = ["/bob"]
282+ [users.admin]
283+ prefixes = [""]
284+ */
285+
286+ fn verify_upload_permissions ( owner : & str , path : & str ) -> Result < ( ) , String > {
287+ let cfg_content = get_config_content ( ) ;
288+ let cfg: Table = toml:: from_str ( & cfg_content) . unwrap ( ) ;
289+ let users_r = cfg. get ( "users" ) ;
290+ let users = match users_r {
291+ Some ( users) => users,
292+ None => {
293+ println ! ( "No users section in config.toml, ignoring upload path restriction" ) ;
294+ return Ok ( ( ) ) ;
295+ }
296+ } ;
297+ let users_vec = users. as_array ( ) . unwrap ( ) ;
298+ for user in users_vec {
299+ let user_name = user. get ( "name" ) . unwrap ( ) . as_str ( ) . unwrap ( ) ;
300+ let user_prefixes = user. get ( "prefixes" ) . unwrap ( ) ;
301+ let user_prefixes_vec = user_prefixes. as_array ( ) . unwrap ( ) ;
302+ for prefix_value in user_prefixes_vec {
303+ let prefix = prefix_value. as_str ( ) . unwrap ( ) ;
304+ if ( path. starts_with ( prefix) || prefix == "" ) && user_name == owner {
305+ return Ok ( ( ) ) ;
306+ }
307+ }
308+ }
309+ Err ( format ! ( "User {} has no upload permissions for path {}" , owner, path) )
310+ }
311+
273312/*
274313 Upload file from user to remote storage
275314 TBD: Store file in cache as well?
@@ -304,6 +343,14 @@ async fn ax_post_file(headers: HeaderMap, mut multipart: Multipart) -> (StatusCo
304343 let mut file0: Vec < u8 > = Vec :: new ( ) ;
305344 let mut file0_filename: String = "" . to_string ( ) ;
306345
346+ // verify upload permissions, some users have upload permissions only for certain prefix(path)
347+ // check config.toml for upload_prefixes
348+ match verify_upload_permissions ( & owner, & path) {
349+ Ok ( _) => ( ) ,
350+ Err ( e) => return ( StatusCode :: FORBIDDEN , e. to_string ( ) . into_bytes ( ) ) ,
351+ }
352+
353+
307354 while let Some ( field) = multipart. next_field ( ) . await . unwrap ( ) {
308355 let name = field. name ( ) . unwrap ( ) . to_string ( ) ;
309356 //let filename = field.file_name();
0 commit comments