@@ -46,6 +46,7 @@ struct JoshProxyService {
4646    fetch_permits :  Arc < tokio:: sync:: Semaphore > , 
4747    filter_permits :  Arc < tokio:: sync:: Semaphore > , 
4848    poll :  Polls , 
49+     acl :  Option < ( String ,  String ) > , 
4950} 
5051
5152impl  std:: fmt:: Debug  for  JoshProxyService  { 
@@ -244,9 +245,11 @@ async fn do_filter(
244245    temp_ns :  Arc < josh_proxy:: TmpGitNamespace > , 
245246    filter_spec :  String , 
246247    headref :  String , 
248+     user :  String , 
247249)  -> josh:: JoshResult < ( ) >  { 
248250    let  permit = service. filter_permits . acquire ( ) . await ; 
249251    let  heads_map = service. heads_map . clone ( ) ; 
252+     let  acl = service. acl . clone ( ) ; 
250253
251254    let  s = tracing:: span!( tracing:: Level :: TRACE ,  "do_filter worker" ) ; 
252255    let  r = tokio:: task:: spawn_blocking ( move  || { 
@@ -295,7 +298,28 @@ async fn do_filter(
295298
296299        let  mut  headref = headref; 
297300
298-         josh:: filter_refs ( & transaction,  filter,  & from_to,  josh:: filter:: empty ( ) ) ?; 
301+         let  permissions_filter = if  let  Some ( acl)  = acl { 
302+             let  users = & acl. 0 ; 
303+             let  groups = & acl. 1 ; 
304+             tracing:: info!( "User: {:?}, Repo: {:?}" ,  user,  upstream_repo) ; 
305+             let  acl = match  josh:: get_acl ( & users,  & groups,  & user,  & upstream_repo)  { 
306+                 Ok ( acl)  => acl, 
307+                 Err ( e)  => { 
308+                     tracing:: error!( "Failed to read ACL file: {:?}" ,  e) ; 
309+                     ( josh:: filter:: empty ( ) ,  josh:: filter:: nop ( ) ) 
310+                 } 
311+             } ; 
312+             let  whitelist = acl. 0 ; 
313+             let  blacklist = acl. 1 ; 
314+             tracing:: info!( "Whitelist: {:?}, Blacklist: {:?}" ,  whitelist,  blacklist) ; 
315+             josh:: filter:: make_permissions_filter ( filter,  whitelist,  blacklist) 
316+         }  else  { 
317+             josh:: filter:: empty ( ) 
318+         } ; 
319+ 
320+         tracing:: info!( "Permissions: {:?}" ,  permissions_filter) ; 
321+ 
322+         josh:: filter_refs ( & transaction,  filter,  & from_to,  permissions_filter) ?; 
299323        if  headref == "HEAD"  { 
300324            headref = heads_map
301325                . read ( ) ?
@@ -517,6 +541,7 @@ async fn call_service(
517541        & parsed_url. upstream_repo , 
518542        & parsed_url. filter , 
519543        & headref, 
544+         & username, 
520545    ) 
521546    . in_current_span ( ) 
522547    . await ?; 
@@ -598,6 +623,7 @@ async fn prepare_namespace(
598623    upstream_repo :  & str , 
599624    filter_spec :  & str , 
600625    headref :  & str , 
626+     user :  & str , 
601627)  -> josh:: JoshResult < std:: sync:: Arc < josh_proxy:: TmpGitNamespace > >  { 
602628    let  temp_ns = Arc :: new ( josh_proxy:: TmpGitNamespace :: new ( 
603629        & serv. repo_path , 
@@ -606,13 +632,16 @@ async fn prepare_namespace(
606632
607633    let  serv = serv. clone ( ) ; 
608634
635+     let  user = if  user == ""  {  "anonymous"  }  else  {  user } ; 
636+ 
609637    do_filter ( 
610638        serv. repo_path . clone ( ) , 
611639        serv. clone ( ) , 
612640        upstream_repo. to_owned ( ) , 
613641        temp_ns. to_owned ( ) , 
614642        filter_spec. to_owned ( ) , 
615643        headref. to_string ( ) , 
644+         user. to_string ( ) , 
616645    ) 
617646    . await ?; 
618647
@@ -635,6 +664,20 @@ async fn run_proxy() -> josh::JoshResult<i32> {
635664    josh_proxy:: create_repo ( & local) ?; 
636665    josh:: cache:: load ( & local) ?; 
637666
667+     let  acl = if  ARGS . is_present ( "users" )  && ARGS . is_present ( "groups" )  { 
668+         println ! ( 
669+             "{}, {}" , 
670+             ARGS . value_of( "users" ) . unwrap( ) . to_string( ) , 
671+             ARGS . value_of( "groups" ) . unwrap( ) . to_string( ) 
672+         ) ; 
673+         Some ( ( 
674+             ARGS . value_of ( "users" ) . unwrap ( ) . to_string ( ) , 
675+             ARGS . value_of ( "groups" ) . unwrap ( ) . to_string ( ) , 
676+         ) ) 
677+     }  else  { 
678+         None 
679+     } ; 
680+ 
638681    let  proxy_service = Arc :: new ( JoshProxyService  { 
639682        port, 
640683        repo_path :  local. to_owned ( ) , 
@@ -646,6 +689,7 @@ async fn run_proxy() -> josh::JoshResult<i32> {
646689            ARGS . value_of ( "n" ) . unwrap_or ( "1" ) . parse ( ) ?, 
647690        ) ) , 
648691        filter_permits :  Arc :: new ( tokio:: sync:: Semaphore :: new ( 10 ) ) , 
692+         acl, 
649693    } ) ; 
650694
651695    let  ps = proxy_service. clone ( ) ; 
@@ -800,6 +844,18 @@ fn parse_args() -> clap::ArgMatches<'static> {
800844                . help ( "Duration between forced cache refresh" ) 
801845                . takes_value ( true ) , 
802846        ) 
847+         . arg ( 
848+             clap:: Arg :: with_name ( "users" ) 
849+                 . long ( "users" ) 
850+                 . takes_value ( true ) 
851+                 . help ( "YAML file listing the groups of the users" ) , 
852+         ) 
853+         . arg ( 
854+             clap:: Arg :: with_name ( "groups" ) 
855+                 . long ( "groups" ) 
856+                 . takes_value ( true ) 
857+                 . help ( "YAML file listing the access rights of the groups" ) , 
858+         ) 
803859        . get_matches_from ( args) 
804860} 
805861
0 commit comments