enhanced the directory restriction of the pre-commit hook configurable

This commit is contained in:
hyung-hwan 2015-02-16 12:27:25 +00:00
parent 63d0c15ef9
commit 827e4b4e87
4 changed files with 100 additions and 67 deletions

View File

@ -2,7 +2,7 @@ Package: @PACKAGE@
Version: @VERSION@
Maintainer: @PACKAGE_BUGREPORT@
Homepage: @PACKAGE_URL@
Depends: subversion, apache2-mpm-prefork, libapache2-svn, php5, php5-ldap, php5-gd, perl, libconfig-simple-perl, libsvn-perl
Depends: subversion, apache2, libapache2-svn, libapache2-mod-perl2, libapache2-mod-php5, php5, php5-ldap, php5-gd, perl, libdbi-perl, libconfig-simple-perl, libsvn-perl, libnet-ldap-perl, libdigest-sha1-perl
Recommends: php5-mysql, php5-svn (>= 0.5.1)
Suggests: slapd, mysql-server
Section: web

View File

@ -199,19 +199,6 @@ allow_set_time_limit = "no"
;------------------------------------------------------------------------------
signin_for_code_search = "yes"
;------------------------------------------------------------------------------
; Subversion read access is limited to the specified user type. The types
; include anonymous, authenticated, member. This applies to a public project
; only. Write access to any projects and read access to a non-public project
; require membership regardless of this item.
;------------------------------------------------------------------------------
svn_read_access = "member"
;------------------------------------------------------------------------------
; The length of a commit message must be as long as this value.
;------------------------------------------------------------------------------
svn_min_commit_message_length = "0"
;------------------------------------------------------------------------------
; customized footer
@ -226,3 +213,24 @@ footer = ""
; Full path to the CLOC command
;------------------------------------------------------------------------------
cloc_command_path = "@CFGDIR@/cloc.pl"
;------------------------------------------------------------------------------
; Subversion read access is limited to the specified user type. The types
; include anonymous, authenticated, member. This applies to a public project
; only. Write access to any projects and read access to a non-public project
; require membership regardless of this item.
;------------------------------------------------------------------------------
svn_read_access = "member"
;------------------------------------------------------------------------------
; The length of a commit message must be as long as this value.
;------------------------------------------------------------------------------
svn_min_commit_message_length = "0"
;------------------------------------------------------------------------------
; The operations on the files under one of svn_restricted_topdirs
; is limited. The value can be separated by a comma.
;------------------------------------------------------------------------------
svn_restricted_topdirs = ""
svn_restriction_allowed_subdir_depth_min = 1
svn_restriction_allowed_subdir_depth_max = 1

View File

@ -48,8 +48,11 @@ sub get_config
database_name => $cfg->param ('database_name'),
database_driver => $cfg->param ('database_driver'),
database_prefix => $cfg->param ('database_prefix'),
svn_min_commit_message_length => $cfg->param ('svn_min_commit_message_length')
svn_min_commit_message_length => $cfg->param ('svn_min_commit_message_length'),
svn_restricted_topdirs => $cfg->param('svn_restricted_topdirs'),
svn_restriction_allowed_subdir_depth_min => $cfg->param('svn_restriction_allowed_subdir_depth_min'),
svn_restriction_allowed_subdir_depth_max => $cfg->param('svn_restriction_allowed_subdir_depth_max')
};
return $config;
@ -314,9 +317,9 @@ sub restrict_changes_in_directory_old
return ($disallowed > 0)? -1: 0;
}
sub restrict_changes_in_directory
sub restrict_changes_in_topdirs
{
my ($dir, $min_level, $max_level) = @_;
my ($min_level, $max_level, @topdirs) = @_;
my $disallowed = 0;
my $pool = SVN::Pool->new(undef);
@ -392,64 +395,66 @@ sub restrict_changes_in_directory
#print STDERR "@@@@@ [$affected_file] [$action_verb] [$source_file] [$is_source_file_dir] [$is_affected_file_dir]\n";
if ($affected_file =~ /\/${dir}\/(.*)$/)
foreach my $topdir(@topdirs)
{
# the affected file is located under the given directory.
my $affected_file_nodir = "${1}";
if (defined($source_file))
if ($affected_file =~ /\/${topdir}\/(.*)$/)
{
# it's being copied.
if (!$is_affected_file_dir)
# the affected file is located under the given directory.
my $affected_file_nodir = "${1}";
if (defined($source_file))
{
# the file beging added by copying is not a directory.
# it disallows individual file copying.
# copy a whole directory at one go.
print (STDERR "Disallowed to copy ${source_file} to ${affected_file}\n");
$disallowed++;
}
elsif ($source_file =~ /^\/${dir}\/(.*)$/)
{
# i don't want to be a copied file or directory to be
# a source of another copy operation.
print (STDERR "Disallowed to copy ${source_file} to ${affected_file}\n");
$disallowed++;
# it's being copied.
if (!$is_affected_file_dir)
{
# the file beging added by copying is not a directory.
# it disallows individual file copying.
# copy a whole directory at one go.
print (STDERR "Disallowed to copy ${source_file} to ${affected_file}\n");
$disallowed++;
}
elsif ($source_file =~ /^\/${topdir}\/(.*)$/)
{
# i don't want to be a copied file or directory to be
# a source of another copy operation.
print (STDERR "Disallowed to copy ${source_file} to ${affected_file}\n");
$disallowed++;
}
else
{
# TODO: DISALLOW THIS if the parent directory is a copied directory
#my $pardir = dirname ($affected_file);
}
}
else
{
# TODO: DISALLOW THIS if the parent directory is a copied directory
#my $pardir = dirname ($affected_file);
}
}
else
{
if ($is_affected_file_dir)
{
my @segs = split ('/', $affected_file_nodir);
my $num_segs = scalar(@segs);
# NOTE: for a string like abc/def/, split() seems to return 2 segments only.
if ($is_affected_file_dir)
{
my @segs = split ('/', $affected_file_nodir);
my $num_segs = scalar(@segs);
# NOTE: for a string like abc/def/, split() seems to return 2 segments only.
if ($affected_file_nodir eq '')
{
# it is the main directory itself.
# allow operation on it.
if ($affected_file_nodir eq '')
{
# it is the main directory itself.
# allow operation on it.
}
elsif ($num_segs < $min_level || $num_segs > $max_level)
{
# disallow deletion if the directory name to be deleted
# matches a tag pattern
print (STDERR "Disallowed to ${action_verb} a directory - ${affected_file}\n");
$disallowed++;
}
}
elsif ($num_segs < $min_level || $num_segs > $max_level)
else
{
# disallow deletion if the directory name to be deleted
# matches a tag pattern
print (STDERR "Disallowed to ${action_verb} a directory - ${affected_file}\n");
print (STDERR "Disallowed to ${action_verb} a file - ${affected_file}\n");
$disallowed++;
}
}
else
{
print (STDERR "Disallowed to ${action_verb} a file - ${affected_file}\n");
$disallowed++;
}
}
}
}
# 'svn rename' within the restricted directory is disallowed because
@ -482,10 +487,24 @@ if (check_commit_message ($cfg->{svn_min_commit_message_length}) <= 0)
exit (1);
}
# TODO: make 'tags' and 'min_level', 'max_level' configurable.
if (restrict_changes_in_directory ('tags', 1, 2) <= -1)
# TODO: enable per-project settings for topdir restriction
my $min_level = $cfg->{svn_restriction_allowed_subdir_depth_min};
if (!defined($min_level)) { $min_level = 0; }
my $max_level = $cfg->{svn_restriction_allowed_subdir_depth_max};
if (!defined($max_level)) { $max_level = 0; }
my $topdirs = $cfg->{svn_restricted_topdirs};
if (defined($topdirs))
{
exit (1);
my @topdir_array = split (/\s*,\s*/, $topdirs);
if (scalar(@topdir_array) > 0)
{
if (restrict_changes_in_topdirs ($min_level, $max_level, @topdir_array) <= -1)
{
exit (1);
}
}
}
#my $dbh = open_database ($cfg);

View File

@ -78,10 +78,16 @@ function load_ini ($file)
array ('force_project_delete', 'boolean', FALSE),
array ('allow_set_time_limit', 'boolean', FALSE),
array ('signin_for_code_search', 'boolean', TRUE),
array ('svn_for_members_only', 'boolean', FALSE),
array ('footer', 'string', ''),
array ('cloc_command_path', 'string', CODEPOT_CFG_DIR.'/cloc.pl')
array ('cloc_command_path', 'string', CODEPOT_CFG_DIR.'/cloc.pl'),
// these items are not used by php but by subersion hooks written in perl.
array ('svn_read_access', 'string', 'member'),
array ('svn_min_commit_message_length', 'integer', 0),
array ('svn_restricted_topdirs', 'string', ''),
array ('svn_restriction_allowed_subdir_depth_min', 'integer', 0),
array ('svn_restriction_allowed_subdir_depth_max', 'integer', 0)
);
foreach ($xcfgs as $x)