@@ -46,6 +46,7 @@ struct JoshProxyService {
46
46
fetch_permits : Arc < tokio:: sync:: Semaphore > ,
47
47
filter_permits : Arc < tokio:: sync:: Semaphore > ,
48
48
poll : Polls ,
49
+ acl : Option < ( String , String ) > ,
49
50
}
50
51
51
52
impl std:: fmt:: Debug for JoshProxyService {
@@ -244,9 +245,11 @@ async fn do_filter(
244
245
temp_ns : Arc < josh_proxy:: TmpGitNamespace > ,
245
246
filter_spec : String ,
246
247
headref : String ,
248
+ user : String ,
247
249
) -> josh:: JoshResult < ( ) > {
248
250
let permit = service. filter_permits . acquire ( ) . await ;
249
251
let heads_map = service. heads_map . clone ( ) ;
252
+ let acl = service. acl . clone ( ) ;
250
253
251
254
let s = tracing:: span!( tracing:: Level :: TRACE , "do_filter worker" ) ;
252
255
let r = tokio:: task:: spawn_blocking ( move || {
@@ -295,7 +298,29 @@ async fn do_filter(
295
298
296
299
let mut headref = headref;
297
300
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
+ {
307
+ Ok ( acl) => acl,
308
+ Err ( e) => {
309
+ tracing:: error!( "Failed to read ACL file: {:?}" , e) ;
310
+ ( josh:: filter:: empty ( ) , josh:: filter:: nop ( ) )
311
+ }
312
+ } ;
313
+ let whitelist = acl. 0 ;
314
+ let blacklist = acl. 1 ;
315
+ tracing:: info!( "Whitelist: {:?}, Blacklist: {:?}" , whitelist, blacklist) ;
316
+ josh:: filter:: make_permissions_filter ( filter, whitelist, blacklist)
317
+ } else {
318
+ josh:: filter:: empty ( )
319
+ } ;
320
+
321
+ tracing:: info!( "Permissions: {:?}" , permissions_filter) ;
322
+
323
+ josh:: filter_refs ( & transaction, filter, & from_to, permissions_filter) ?;
299
324
if headref == "HEAD" {
300
325
headref = heads_map
301
326
. read ( ) ?
@@ -517,6 +542,7 @@ async fn call_service(
517
542
& parsed_url. upstream_repo ,
518
543
& parsed_url. filter ,
519
544
& headref,
545
+ & username,
520
546
)
521
547
. in_current_span ( )
522
548
. await ?;
@@ -598,6 +624,7 @@ async fn prepare_namespace(
598
624
upstream_repo : & str ,
599
625
filter_spec : & str ,
600
626
headref : & str ,
627
+ user : & str ,
601
628
) -> josh:: JoshResult < std:: sync:: Arc < josh_proxy:: TmpGitNamespace > > {
602
629
let temp_ns = Arc :: new ( josh_proxy:: TmpGitNamespace :: new (
603
630
& serv. repo_path ,
@@ -606,13 +633,16 @@ async fn prepare_namespace(
606
633
607
634
let serv = serv. clone ( ) ;
608
635
636
+ let user = if user == "" { "anonymous" } else { user } ;
637
+
609
638
do_filter (
610
639
serv. repo_path . clone ( ) ,
611
640
serv. clone ( ) ,
612
641
upstream_repo. to_owned ( ) ,
613
642
temp_ns. to_owned ( ) ,
614
643
filter_spec. to_owned ( ) ,
615
644
headref. to_string ( ) ,
645
+ user. to_string ( ) ,
616
646
)
617
647
. await ?;
618
648
@@ -635,6 +665,20 @@ async fn run_proxy() -> josh::JoshResult<i32> {
635
665
josh_proxy:: create_repo ( & local) ?;
636
666
josh:: cache:: load ( & local) ?;
637
667
668
+ let acl = if ARGS . is_present ( "users" ) && ARGS . is_present ( "groups" ) {
669
+ println ! (
670
+ "{}, {}" ,
671
+ ARGS . value_of( "users" ) . unwrap( ) . to_string( ) ,
672
+ ARGS . value_of( "groups" ) . unwrap( ) . to_string( )
673
+ ) ;
674
+ Some ( (
675
+ ARGS . value_of ( "users" ) . unwrap ( ) . to_string ( ) ,
676
+ ARGS . value_of ( "groups" ) . unwrap ( ) . to_string ( ) ,
677
+ ) )
678
+ } else {
679
+ None
680
+ } ;
681
+
638
682
let proxy_service = Arc :: new ( JoshProxyService {
639
683
port,
640
684
repo_path : local. to_owned ( ) ,
@@ -646,6 +690,7 @@ async fn run_proxy() -> josh::JoshResult<i32> {
646
690
ARGS . value_of ( "n" ) . unwrap_or ( "1" ) . parse ( ) ?,
647
691
) ) ,
648
692
filter_permits : Arc :: new ( tokio:: sync:: Semaphore :: new ( 10 ) ) ,
693
+ acl,
649
694
} ) ;
650
695
651
696
let ps = proxy_service. clone ( ) ;
@@ -800,6 +845,18 @@ fn parse_args() -> clap::ArgMatches<'static> {
800
845
. help ( "Duration between forced cache refresh" )
801
846
. takes_value ( true ) ,
802
847
)
848
+ . arg (
849
+ clap:: Arg :: with_name ( "users" )
850
+ . long ( "users" )
851
+ . takes_value ( true )
852
+ . help ( "YAML file listing the groups of the users" ) ,
853
+ )
854
+ . arg (
855
+ clap:: Arg :: with_name ( "groups" )
856
+ . long ( "groups" )
857
+ . takes_value ( true )
858
+ . help ( "YAML file listing the access rights of the groups" ) ,
859
+ )
803
860
. get_matches_from ( args)
804
861
}
805
862
0 commit comments