package SVN::ACL;

use strict;
use YAML;

our $VERSION = '0.02';

sub new {
    my $class = shift;
    my $path = shift;
    my $perm;
    
    my $aclfile = "$path/YAML.conf";
    (-w $path) or die "Can't access the config file: $aclfile";
    if (-e $aclfile) {
	$perm = YAML::LoadFile($aclfile);
    } 
    else {
	$perm->{dir}->{'/'}->{'*'} = 'r';

    }
    bless ( { path => $path,
	      perm => $perm }, $class );
}

sub newdir {
    my $self = shift;
    my $dir = shift;
    $self->{perm}->{dir}->{$dir}->{'*'} = '';
}

sub newuser {
    my $self = shift;
    my ($name, $password) = @_;
    $self->{perm}->{user}->{$name} = $password;
}

sub deluser {
    my $self = shift;
    my $name = shift;
    delete $self->{perm}->{user}->{$name};
}

sub newgroup {
    my $self = shift;
    my $group = shift;
    $self->{perm}->{group}->{"@".$group} = [];
}

sub delgroup {
    my $self = shift;
    my $group = shift;
    delete $self->{perm}->{group}->{"@".$group};
}

sub grant {
    my $self = shift;
    my ($dir, $user, $permission) = @_;
    if ($user =~ /^@/) {
    exists ($self->{perm}->{group}->{$user}) 
	or die "no such group, you have to new the user first";
    $permission ? $self->{perm}->{dir}->{$dir}->{$user} = $permission 
		: delete $self->{perm}->{dir}->{$dir}->{$user};
    }
    else {
    # $self->newdir($dir) unless (exists $self->{perm}->{dir}->{$dir});
	exists ($self->{perm}->{user}->{$user}) 
	    or die "no such user, you have to new the user first";
	$permission ? $self->{perm}->{dir}->{$dir}->{$user} = $permission 
		   : delete $self->{perm}->{dir}->{$dir}->{$user};
    }
}

sub togroup {
    my $self = shift;
    my ($user, $group) = @_;
    $group = "@".$group;
    $self->{perm}->{group}->{$group} = [] unless (exists $self->{perm}->{group}->{$group});
    push @{$self->{perm}->{group}->{$group}}, $user;
}

sub export {
    my $self = shift;
    my $repospath = $self->{path};
    # parse the svnserv.conf
    open SVNSERV, ">$repospath/conf/svnserve.conf" or die $!;
    print SVNSERV << "CONF";
[general]
anon-access = read
auth-access = write
password-db = passwd
authz-db = authz
CONF
    close SVNSERV;
    # parse passwd file
    open PASSWD, ">$repospath/conf/passwd" or die $!;
    print PASSWD "[users]\n";
    print PASSWD "$_ = ".$self->{perm}->{user}->{$_}."\n" for keys %{$self->{perm}->{user}};
    close PASSWD;
    # parse authz
    open AUTHZ, ">$repospath/conf/authz" or die $!;
    print AUTHZ "[groups]\n";
    for (keys %{$self->{perm}->{group}}) {
	my $users = join ",", @{$self->{perm}->{group}->{$_}};
	print AUTHZ "$_ = $users\n" 
    }
    print AUTHZ "\n\n";
    for my $path (keys %{$self->{perm}->{dir}}) {
	print AUTHZ "[$path]\n";
	for (keys %{$self->{perm}->{dir}->{$path}}) {
	    print AUTHZ "$_ = ".$self->{perm}->{dir}->{$path}->{$_}."\n";
	}
	print AUTHZ "\n";
    }
    close AUTHZ;
}

sub save {
    my $self = shift;
    my $aclfile = $self->{path}."/YAML.conf";
    YAML::DumpFile($aclfile, $self->{perm});
}

1;

__END__

=head1 NAME

SVN::ACL is a simple fronend to make the svnserve.conf, passwd, authz for Subversion.To use the mod_dav_svn, it requires the subversion 1.3.0 or later. 

=head1 VERSION

This document describes version 0.01 of SVN::ACL, released 
January 16, 2006.

=head1 SYNOPSIS

use SVN::ACL;

my $acl = SVN::ACL->initi('repos', '/use/local/svn/');
$acl->newuser('hcchien', 'hcchien');
$acl->newgroup('rt3')
$acl->togroup('hcchien', 'rt3');
$acl->grant('/foo', 'hcchien', 'rw');
$acl->grant('/bar', 'chien', '');     # it will remove user chien from directory bar
$acl->export;

=head1 DESCRIPTION

After subversion 1.3.0, it offers the new access control for using the svnserve. When you use svnadmin to create a new subversion repository. The svnserve.conf, passwd and authz will be generated by subversion automatically. You can config the files by yourself manually. SVN::ACL just offers the simple frondend to do the same thing. SVN::ACL will use the YAML to do the dirty jobs.

=head1 AUTHORS

Hsin-Chan Chien E<lt>hcchien@hcchien.orgE<gt>

=head1 COPYRIGHT

Copyright 2005 by Hsin-Chan Chien E<lt>hcchien@hcchien.orgE<gt>.

This program is free software; you can redistribute it and/or 
modify it under the same terms as Perl itself.

See L<http://www.perl.com/perl/misc/Artistic.html>

=cut
