wildrepos almost done (except setperms etc)
implementation notes - new sugar role_names() to prefix an "@" to CREATOR, and any role names listed in the rc file. - invalidate the cache in rules() if the repo was missing. Without this, an auto-create operation succeeds the ^C check and calls new_wild_repo(), but then -- due to the cached rules not containing a rule for CREATOR, the actual read/write fails. - treat roles (READERS, WRITERS, etc.) as group names that apply only to that particular repo. Don't add them to %groups, because that would screw up caching, but add them in when memberships() is called for the user. This is why the membership call for the user also has a reponame tacked on -- i.e., a user's membership list varied depending on which repo you're talking about. - while we're about it, pretend we added "CREATOR = <content of gl-creator>" as another "role". Makes things so much easier dealing with "RW+ = CREATOR" - searching for rules pertaining to foo/CREATOR/bar when looking at repo foo/sitaram/bar is done backwards from what g2 used to do. G2 used to play tricks with the do-eval'd file using global variables so that what you get after the do may not even contain 'CREATOR'. We go the other way. We replace sitaram with CREATOR and start looking for memberships of *both* foo/sitaram/bar and foo/CREATOR/bar. - this doesn't work (because we don't know *what* to replace) for missing repos if GL_USER is not set. This means that 'gitolite access ...' queries (which do not set GL_USER) cannot be used reliably for non-existant repos. Since a ^C check is the only meaningful one for a non-existent repo, this means you cannot do that from 'gitolite access'. 'GL_USER=luser gitolite info' will still work though ;-) all in all, much cleaner and simpler than g2.
This commit is contained in:
parent
3c5ae7f26b
commit
1b31c21440
|
@ -229,6 +229,9 @@ sub load_1 {
|
||||||
$lastuser = $user;
|
$lastuser = $user;
|
||||||
@cached = @rules;
|
@cached = @rules;
|
||||||
|
|
||||||
|
# however if the repo was missing, invalidate the cache
|
||||||
|
$lastrepo = '' if repo_missing($repo);
|
||||||
|
|
||||||
return @rules;
|
return @rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,44 +312,60 @@ sub user_roles {
|
||||||
|
|
||||||
my %ret = ();
|
my %ret = ();
|
||||||
my $f = "$rc{GL_REPO_BASE}/$repo.git/gl-perms";
|
my $f = "$rc{GL_REPO_BASE}/$repo.git/gl-perms";
|
||||||
|
my @roles = ();
|
||||||
if ( -f $f ) {
|
if ( -f $f ) {
|
||||||
my $fh = _open( "<", $f );
|
my $fh = _open( "<", $f );
|
||||||
while (<$fh>) {
|
chomp(@roles = <$fh>);
|
||||||
chomp;
|
}
|
||||||
# READERS u3 u4 @g1
|
push @roles, "CREATOR = " . creator($repo);
|
||||||
s/^\s+//; s/ +$//; s/=/ /; s/\s+/ /g; s/\@//;
|
for (@roles) {
|
||||||
my ( $role, @members ) = split;
|
# READERS u3 u4 @g1
|
||||||
# role = READERS, members = u3, u4, @g1
|
s/^\s+//; s/ +$//; s/=/ /; s/\s+/ /g; s/^\@//;
|
||||||
if ( not $rc{ROLES}{$role} ) {
|
my ( $role, @members ) = split;
|
||||||
_warn "role '$role' not allowed, ignoring";
|
# role = READERS, members = u3, u4, @g1
|
||||||
|
if ( $role ne 'CREATOR' and not $rc{ROLES}{$role} ) {
|
||||||
|
_warn "role '$role' not allowed, ignoring";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
for my $m (@members) {
|
||||||
|
if ( $m !~ $USERNAME_PATT ) {
|
||||||
|
_warn "ignoring '$m' in perms line";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
for my $m (@members) {
|
# if user eq u3/u4, or is a member of @g1, he has role READERS
|
||||||
if ( $m !~ $USERNAME_PATT ) {
|
$ret{ '@' . $role } = 1 if $m eq $user or $eg{$m};
|
||||||
_warn "ignoring '$m' in perms line";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
# if user eq u3/u4, or is a member of @g1, he has role READERS
|
|
||||||
$ret{ '@' . $role } = 1 if $m eq $user or $eg{$m};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return keys %ret;
|
return keys %ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub generic_name {
|
sub generic_name {
|
||||||
my $base = shift;
|
my $base = shift;
|
||||||
my $base2 = '';
|
my $base2 = '';
|
||||||
my $f = "$rc{GL_REPO_BASE}/$base.git/gl-creator";
|
my $creator;
|
||||||
if ( -f $f ) {
|
|
||||||
my $creator;
|
# get the creator name. For not-yet-born repos this is $ENV{GL_USER},
|
||||||
chomp( $creator = slurp($f) );
|
# which should be set in all cases that we care about, viz., where we are
|
||||||
( $base2 = $base ) =~ s(/$creator/)(/CREATOR/);
|
# checking ^C permissions before new_wild_repo(), and the info command.
|
||||||
$base2 = '' if $base2 eq $base; # if there was no change
|
# In particular, 'gitolite access' can't be used to check ^C perms.
|
||||||
}
|
$creator = creator($base);
|
||||||
|
|
||||||
|
( $base2 = $base ) =~ s(/$creator/)(/CREATOR/) if $creator;
|
||||||
|
$base2 = '' if $base2 eq $base; # if there was no change
|
||||||
|
|
||||||
return $base2;
|
return $base2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub creator {
|
||||||
|
my $repo = shift;
|
||||||
|
return ( $ENV{GL_USER} || '' ) if repo_missing($repo);
|
||||||
|
my $f = "$rc{GL_REPO_BASE}/$repo.git/gl-creator";
|
||||||
|
my $creator = '';
|
||||||
|
chomp( $creator = slurp($f) ) if -f $f;
|
||||||
|
return $creator;
|
||||||
|
}
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# api functions
|
# api functions
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
|
@ -67,6 +67,7 @@ sub sugar {
|
||||||
$lines = option($lines); # must come after rw_cdm
|
$lines = option($lines); # must come after rw_cdm
|
||||||
$lines = owner_desc($lines);
|
$lines = owner_desc($lines);
|
||||||
$lines = name_vref($lines);
|
$lines = name_vref($lines);
|
||||||
|
$lines = role_names($lines);
|
||||||
|
|
||||||
return $lines;
|
return $lines;
|
||||||
}
|
}
|
||||||
|
@ -173,5 +174,30 @@ sub name_vref {
|
||||||
return \@ret;
|
return \@ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub role_names {
|
||||||
|
my $lines = shift;
|
||||||
|
my @ret;
|
||||||
|
|
||||||
|
# <perm> [<ref>] = <user list containing CREATOR|READERS|WRITERS>
|
||||||
|
# -> same but with "@" prepended to rolenames
|
||||||
|
|
||||||
|
for my $line (@$lines) {
|
||||||
|
if ( $line =~ /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/ ) {
|
||||||
|
my($p, $r) = ($1, $2);
|
||||||
|
my $u = '';
|
||||||
|
for (split ' ', $3) {
|
||||||
|
$_ = "\@$_" if $_ eq 'CREATOR' or $rc{ROLES}{$_};
|
||||||
|
$u .= " $_";
|
||||||
|
}
|
||||||
|
$r ||= '';
|
||||||
|
# mind the spaces (or play safe and run cleanup_conf_line again)
|
||||||
|
push @ret, cleanup_conf_line("$p $r = $u");
|
||||||
|
} else {
|
||||||
|
push @ret, $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return \@ret;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue