# -*- cperl -*- use 5.010; use strict; use warnings; use lib 't'; use Test::More tests => 27; BEGIN { require "test-functions.pl" }; my ($repo, $file, $clone) = new_repos(); foreach my $git ($repo, $clone) { install_hooks($git, undef, qw/update pre-receive/); } sub check_can_push { my ($testname, $ref) = @_; new_commit($repo, $file); test_ok($testname, $repo, 'push', '--tags', $clone->repo_path(), $ref || 'master'); } sub check_cannot_push { my ($testname, $ref, $error) = @_; new_commit($repo, $file); test_nok_match($testname, $error || qr/\) cannot \S+ ref /, $repo, 'push', '--tags', $clone->repo_path(), $ref || 'master'); } # Enable plugin $clone->command(config => 'githooks.update', 'check-acls'); # Without any specific configuration all pushes are denied $ENV{USER} //= 'someone'; # guarantee that the user is known, at least. check_cannot_push('deny by default'); # Check if disabling by ENV is working $ENV{CheckAcls} = 0; check_can_push('allow if plugin is disabled by ENV'); delete $ENV{CheckAcls}; # Configure admin environment variable $clone->command(config => 'check-acls.userenv', 'ACL_ADMIN'); $clone->command(config => 'check-acls.admin', 'admin'); $ENV{'ACL_ADMIN'} = 'admin2'; check_cannot_push('deny if not admin'); $ENV{'ACL_ADMIN'} = 'admin'; check_can_push('allow if admin user'); $clone->command(config => '--replace-all', 'check-acls.admin', '^adm'); check_can_push('allow if admin matches regex'); $clone->command(config => '--replace-all', 'check-acls.userenv', 'eval:x y z'); check_cannot_push('disallow if userenv cannot eval', 'master', qr/error evaluating userenv value/); $clone->command(config => '--replace-all', 'check-acls.userenv', 'eval:"nouser"'); check_cannot_push('disallow if userenv eval to nouser'); $clone->command(config => '--replace-all', 'check-acls.userenv', 'eval:$ENV{ACL_ADMIN}'); check_can_push('allow if userenv can eval'); # Configure groups $clone->command(config => 'githooks.groups', <<'EOF'); admins1 = admin admins = @admins1 EOF $clone->command(config => '--replace-all', 'check-acls.admin', '@admins'); check_can_push('allow if admin in group'); $clone->command(config => '--unset', 'check-acls.admin'); $clone->command(config => 'check-acls.acl', 'admin U master'); check_cannot_push('deny ACL master'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin U refs/heads/master'); check_can_push('allow ACL refs/heads/master'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin U refs/heads/branch'); check_cannot_push('deny ACL other ref'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin U ^.*/master'); check_can_push('allow ACL regex ref'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin U !master'); check_cannot_push('deny ACL negated regex ref'); $clone->command(config => '--replace-all', 'check-acls.acl', '^adm U refs/heads/master'); check_can_push('allow ACL regex user'); delete $ENV{VAR}; $clone->command(config => '--replace-all', 'check-acls.acl', '^adm U refs/heads/{VAR}'); check_cannot_push('deny ACL non-interpolated ref'); $ENV{VAR} = 'master'; $clone->command(config => '--replace-all', 'check-acls.acl', '^adm U refs/heads/{VAR}'); check_can_push('allow ACL interpolated ref'); $clone->command(config => '--replace-all', 'check-acls.acl', '@admins U refs/heads/master'); check_can_push('allow ACL user in group '); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin DUR refs/heads/fix'); $repo->command(checkout => '-q', '-b', 'fix'); check_cannot_push('deny ACL create ref', 'heads/fix'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin C refs/heads/fix'); check_can_push('allow create ref', 'heads/fix'); $repo->command(checkout => '-q', 'master'); $repo->command(branch => '-D', 'fix'); check_cannot_push('deny ACL delete ref', ':refs/heads/fix'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin D refs/heads/fix'); check_can_push('allow ACL delete ref', ':refs/heads/fix'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin U refs/heads/master'); check_can_push('allow ACL refs/heads/master again, to force a successful push'); $clone->command(config => '--replace-all', 'check-acls.acl', 'admin CDU refs/heads/master'); $repo->command(reset => '--hard', 'HEAD~2'); # rewind fix locally check_cannot_push('deny ACL rewrite ref', '+master:master'); # try to push it $clone->command(config => '--replace-all', 'check-acls.acl', 'admin R refs/heads/master'); check_can_push('allow ACL rewrite ref', '+master:master'); # try to push it $clone->command(config => '--replace-all', 'check-acls.acl', 'admin CRUD refs/heads/master'); $repo->command(tag => '-a', '-mtag', 'objtag'); # object tag check_cannot_push('deny ACL push tag'); $clone->command(config => '--add', 'check-acls.acl', 'admin CRUD ^refs/tags/'); check_can_push('allow ACL push tag');