aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2007-10-10 23:20:53 +0000
committerRuss Allbery <rra@stanford.edu>2007-10-10 23:20:53 +0000
commitc940a0f4716b0c8048c46ab3e783f543d190eed6 (patch)
tree0354ade71a91d1c3cb1f78bc2ee12e8e4284c0b6
parent5370a35b615d5d868829ba52748208d9f1b129a5 (diff)
Add a history method to the Wallet::ACL API.
-rw-r--r--perl/Wallet/ACL.pm42
-rwxr-xr-xperl/t/acl.t25
2 files changed, 64 insertions, 3 deletions
diff --git a/perl/Wallet/ACL.pm b/perl/Wallet/ACL.pm
index a5ea6f3..6a07366 100644
--- a/perl/Wallet/ACL.pm
+++ b/perl/Wallet/ACL.pm
@@ -17,12 +17,13 @@ use strict;
use vars qw(%MAPPING $VERSION);
use DBI;
+use POSIX qw(strftime);
use Wallet::ACL::Krb5;
# This version should be increased on any code change to this module. Always
# use two digits for the minor version with a leading zero if necessary so
# that it will sort properly.
-$VERSION = '0.01';
+$VERSION = '0.02';
# This is a mapping of schemes to class names, used to determine which ACL
# verifier should be instantiated for a given ACL scheme. Currently, there's
@@ -299,6 +300,34 @@ sub show {
return $output;
}
+# Return as a string the history of an ACL. Returns undef on failure.
+sub history {
+ my ($self) = @_;
+ my $output = '';
+ eval {
+ my $sql = 'select ah_action, ah_scheme, ah_identifier, ah_by, ah_from,
+ ah_on from acl_history where ah_acl = ? order by ah_on';
+ my $sth = $self->{dbh}->prepare ($sql);
+ $sth->execute ($self->{id});
+ my @data;
+ while (@data = $sth->fetchrow_array) {
+ my $time = strftime ('%Y-%m-%d %H:%M:%S', localtime $data[5]);
+ $output .= "$time ";
+ if ($data[0] eq 'add' or $data[0] eq 'remove') {
+ $output .= "$data[0] $data[1] $data[2]";
+ } else {
+ $output .= $data[0];
+ }
+ $output .= "\n by $data[3] from $data[4]\n";
+ }
+ };
+ if ($@) {
+ $self->error ("cannot read history for $self->{id}: $@");
+ return undef;
+ }
+ return $output;
+}
+
# Given a principal, check whether it should be granted access according to
# this ACL. Returns 1 if access was granted, 0 if access was denied, and
# undef on some error. Errors from ACL verifiers do not cause an error
@@ -375,6 +404,8 @@ Wallet::ACL - Implementation of ACLs in the wallet system
}
$acl->remove ('krb5', 'bob@EXAMPLE.COM', $admin, $host);
my @entries = $acl->list;
+ my $summary = $acl->show;
+ my $history = $acl->history;
$acl->destroy ($admin, $host);
=head1 DESCRIPTION
@@ -469,6 +500,15 @@ Returns the error of the last failing operation or undef if no operations
have failed. Callers should call this function to get the error message
after an undef return from any other instance method.
+=item history()
+
+Returns the human-readable history of this ACL. Each action that changes
+the ACL (not including changes to the name of the ACL) will be represented
+by two lines. The first line will have a timestamp of the change followed
+by a description of the change, and the second line will give the user who
+made the change and the host from which the change was made. On failure,
+returns undef, and the caller should call error() to get the error message.
+
=item id()
Returns the numeric system-generated ID of this ACL.
diff --git a/perl/t/acl.t b/perl/t/acl.t
index 644ea3e..bd055d2 100755
--- a/perl/t/acl.t
+++ b/perl/t/acl.t
@@ -8,7 +8,8 @@
#
# See LICENSE for licensing terms.
-use Test::More tests => 100;
+use POSIX qw(strftime);
+use Test::More tests => 101;
use Wallet::ACL;
use Wallet::Config;
@@ -24,7 +25,7 @@ my $admin = 'admin@EXAMPLE.COM';
my $user1 = 'alice@EXAMPLE.COM';
my $user2 = 'bob@EXAMPLE.COM';
my $host = 'localhost';
-my @trace = ($admin, $host);
+my @trace = ($admin, $host, time);
# Use Wallet::Server to set up the database.
my $server = eval { Wallet::Server->initialize ($admin) };
@@ -187,6 +188,26 @@ is ($acl->show, "Members of ACL example (id: 2) are:\n", ' and show concurs');
is ($acl->check ($user2), 0, ' and the second user check fails');
is (scalar ($acl->check_errors), '', ' with no error message');
+# Test history.
+my $date = strftime ('%Y-%m-%d %H:%M:%S', localtime $trace[2]);
+my $history = <<"EOO";
+$date create
+ by $admin from $host
+$date add krb5 $user1
+ by $admin from $host
+$date add krb5 $user2
+ by $admin from $host
+$date remove krb5 $user1
+ by $admin from $host
+$date add krb5
+ by $admin from $host
+$date remove krb5 $user2
+ by $admin from $host
+$date remove krb5
+ by $admin from $host
+EOO
+is ($acl->history, $history, 'History is correct');
+
# Test destroy.
if ($acl->destroy (@trace)) {
ok (1, 'Destroying the ACL works');