@@ -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,28 @@ 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
+ 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) ?;
299
323
if headref == "HEAD" {
300
324
headref = heads_map
301
325
. read ( ) ?
@@ -517,6 +541,7 @@ async fn call_service(
517
541
& parsed_url. upstream_repo ,
518
542
& parsed_url. filter ,
519
543
& headref,
544
+ & username,
520
545
)
521
546
. in_current_span ( )
522
547
. await ?;
@@ -598,6 +623,7 @@ async fn prepare_namespace(
598
623
upstream_repo : & str ,
599
624
filter_spec : & str ,
600
625
headref : & str ,
626
+ user : & str ,
601
627
) -> josh:: JoshResult < std:: sync:: Arc < josh_proxy:: TmpGitNamespace > > {
602
628
let temp_ns = Arc :: new ( josh_proxy:: TmpGitNamespace :: new (
603
629
& serv. repo_path ,
@@ -606,13 +632,16 @@ async fn prepare_namespace(
606
632
607
633
let serv = serv. clone ( ) ;
608
634
635
+ let user = if user == "" { "anonymous" } else { user } ;
636
+
609
637
do_filter (
610
638
serv. repo_path . clone ( ) ,
611
639
serv. clone ( ) ,
612
640
upstream_repo. to_owned ( ) ,
613
641
temp_ns. to_owned ( ) ,
614
642
filter_spec. to_owned ( ) ,
615
643
headref. to_string ( ) ,
644
+ user. to_string ( ) ,
616
645
)
617
646
. await ?;
618
647
@@ -635,6 +664,20 @@ async fn run_proxy() -> josh::JoshResult<i32> {
635
664
josh_proxy:: create_repo ( & local) ?;
636
665
josh:: cache:: load ( & local) ?;
637
666
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
+
638
681
let proxy_service = Arc :: new ( JoshProxyService {
639
682
port,
640
683
repo_path : local. to_owned ( ) ,
@@ -646,6 +689,7 @@ async fn run_proxy() -> josh::JoshResult<i32> {
646
689
ARGS . value_of ( "n" ) . unwrap_or ( "1" ) . parse ( ) ?,
647
690
) ) ,
648
691
filter_permits : Arc :: new ( tokio:: sync:: Semaphore :: new ( 10 ) ) ,
692
+ acl,
649
693
} ) ;
650
694
651
695
let ps = proxy_service. clone ( ) ;
@@ -800,6 +844,18 @@ fn parse_args() -> clap::ArgMatches<'static> {
800
844
. help ( "Duration between forced cache refresh" )
801
845
. takes_value ( true ) ,
802
846
)
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
+ )
803
859
. get_matches_from ( args)
804
860
}
805
861
0 commit comments