@@ -578,6 +578,74 @@ func TestBulkDownload_Success(t *testing.T) {
578578 require .Equal (t , "application/zip" , w .Header ().Get ("Content-Type" ))
579579}
580580
581+ func TestBulkDownload_ACL_NoCredentials (t * testing.T ) {
582+ dir := t .TempDir ()
583+ protected := filepath .Join (dir , "protected" )
584+ require .NoError (t , os .Mkdir (protected , 0755 ))
585+ require .NoError (t , os .WriteFile (filepath .Join (protected , "secret.txt" ), []byte ("secret" ), 0644 ))
586+
587+ hash , err := bcrypt .GenerateFromPassword ([]byte ("pass" ), bcrypt .MinCost )
588+ require .NoError (t , err )
589+ acl := fmt .Sprintf (`{"auth":"user:%s"}` , hash )
590+ require .NoError (t , os .WriteFile (filepath .Join (protected , ".goshs" ), []byte (acl ), 0644 ))
591+
592+ fs , _ := newTestFileServer (t , dir )
593+ r := httptest .NewRequest (http .MethodGet , "/?bulk&file=/protected/secret.txt" , nil )
594+ w := httptest .NewRecorder ()
595+ fs .bulkDownload (w , r )
596+ require .Equal (t , http .StatusUnauthorized , w .Code )
597+ }
598+
599+ func TestBulkDownload_ACL_WithCredentials (t * testing.T ) {
600+ dir := t .TempDir ()
601+ protected := filepath .Join (dir , "protected" )
602+ require .NoError (t , os .Mkdir (protected , 0755 ))
603+ require .NoError (t , os .WriteFile (filepath .Join (protected , "secret.txt" ), []byte ("secret" ), 0644 ))
604+
605+ hash , err := bcrypt .GenerateFromPassword ([]byte ("pass" ), bcrypt .MinCost )
606+ require .NoError (t , err )
607+ acl := fmt .Sprintf (`{"auth":"user:%s"}` , hash )
608+ require .NoError (t , os .WriteFile (filepath .Join (protected , ".goshs" ), []byte (acl ), 0644 ))
609+
610+ fs , _ := newTestFileServer (t , dir )
611+ r := httptest .NewRequest (http .MethodGet , "/?bulk&file=/protected/secret.txt" , nil )
612+ r .Header .Set ("Authorization" , basicAuthHeader ("user" , "pass" ))
613+ w := httptest .NewRecorder ()
614+ fs .bulkDownload (w , r )
615+ require .Equal (t , http .StatusOK , w .Code )
616+ require .Equal (t , "application/zip" , w .Header ().Get ("Content-Type" ))
617+ }
618+
619+ func TestBulkDownload_ACL_BlockList (t * testing.T ) {
620+ dir := t .TempDir ()
621+ require .NoError (t , os .WriteFile (filepath .Join (dir , "blocked.txt" ), []byte ("nope" ), 0644 ))
622+ require .NoError (t , os .WriteFile (filepath .Join (dir , ".goshs" ), []byte (`{"block":["blocked.txt"]}` ), 0644 ))
623+
624+ fs , _ := newTestFileServer (t , dir )
625+ r := httptest .NewRequest (http .MethodGet , "/?bulk&file=/blocked.txt" , nil )
626+ w := httptest .NewRecorder ()
627+ fs .bulkDownload (w , r )
628+ require .Equal (t , http .StatusNotFound , w .Code )
629+ }
630+
631+ func TestBulkDownload_ACL_InheritedFromParent (t * testing.T ) {
632+ dir := t .TempDir ()
633+ sub := filepath .Join (dir , "sub" )
634+ require .NoError (t , os .Mkdir (sub , 0755 ))
635+ require .NoError (t , os .WriteFile (filepath .Join (sub , "file.txt" ), []byte ("data" ), 0644 ))
636+
637+ hash , err := bcrypt .GenerateFromPassword ([]byte ("pass" ), bcrypt .MinCost )
638+ require .NoError (t , err )
639+ acl := fmt .Sprintf (`{"auth":"user:%s"}` , hash )
640+ require .NoError (t , os .WriteFile (filepath .Join (dir , ".goshs" ), []byte (acl ), 0644 ))
641+
642+ fs , _ := newTestFileServer (t , dir )
643+ r := httptest .NewRequest (http .MethodGet , "/?bulk&file=/sub/file.txt" , nil )
644+ w := httptest .NewRecorder ()
645+ fs .bulkDownload (w , r )
646+ require .Equal (t , http .StatusUnauthorized , w .Code )
647+ }
648+
581649// ─── returnJsonDirListing tests ──────────────────────────────────────────────
582650
583651func TestReturnJsonDirListing (t * testing.T ) {
0 commit comments