Added the checkPrivileges method, borrowed from SQLForm.

Wrote tests based on SQLForm bugs to validate it, and it passes.
This commit is contained in:
Colin Kuskie 2007-07-14 23:11:03 +00:00
parent 3d016a366b
commit cff3ac1816
2 changed files with 149 additions and 1 deletions

View file

@ -17,7 +17,9 @@ package WebGUI::DatabaseLink;
use strict;
use Tie::CPHash;
use WebGUI::SQL;
use WebGUI::International;
use WebGUI::Utility;
=head1 NAME
@ -46,6 +48,75 @@ These subroutines are available from this package:
#-------------------------------------------------------------------
=head2 checkPrivileges ( $requestedPrivileges, [$overrideGrants] )
Checks that the database has the requested set of privileges and returns true if it
does.
=head3 requestedPrivileges
An array reference containing the list of privileges to check for this database.
=head3 overrideGrants
An array reference that allows for testing of arbitrary grants. This argument is
solely for testing, as it bypasses querying the database for grants.
=cut
sub checkPrivileges {
my $self = shift;
my $requestedPrivileges = shift;
my $overrideGrants = shift;
##Get the grants for the database, respecting the override if it has
##been passed.
my @grants;
if (defined $overrideGrants) {
@grants = @{ $overrideGrants };
}
else {
@grants = $self->db->buildArray('show grants for current_user');
}
##Parse through the grants, building both the list of grants and the
##database which they belong to.
my @privileges;
foreach (@grants) {
##Checks for grants on all databases '*' or grants on a specific database
if (m/GRANT ([\w\s\d,]*?) ON ([^.]+)/) {
my ($privileges, $database) = ($1, $2);
$database =~ tr/`//d;
$database =~ s/[%*]/.*/g;
if ($self->databaseName() =~ /$database/) {
push(@privileges, (split(/, /,$privileges)));
}
}
}
# Check if we found any privileges at all
if (! scalar @privileges) {
$self->session->errorHandler->warn(
sprintf( "DatabaseLink: Could not find SQL privileges or no privileges on database '%s' for user '%s' with database link ID '%s' using DSN '%s'",
$self->databaseName, $self->get->{username},
$self->getId, $self->get->{DSN},
)
);
return 0;
}
# Check if all required privs are present.
return 1 if (isIn('ALL PRIVILEGES', @privileges));
foreach (@{ $requestedPrivileges }) {
return 0 unless (isIn(uc($_), @privileges));
}
return 1;
}
#-------------------------------------------------------------------
=head2 copy ( )
Returns a new database link id, after copying the properties of this database link to a new entry.

View file

@ -55,7 +55,75 @@ my $DSNs = [
},
];
plan tests => 2 + scalar @{ $DSNs };
#Grants for parsing tests, particularly the database name
my $grants = [
{
dsn => 'DBI:mysql:myDb:myHost:8008',
privileges => [qw/ALTER CREATE INSERT DELETE/],
grants => [
'GRANT ALTER, CREATE, INSERT, DELETE ON *.* to user@localhost',
],
privileged => 1,
comment => 'ACID on *.*, privileged',
},
{
dsn => 'DBI:mysql:myDb:myHost:8008',
privileges => [qw/ALTER CREATE INSERT DELETE/],
grants => [
'GRANT ALL PRIVILEGES ON *.* to user@localhost',
],
privileged => 1,
comment => 'ALL PRIVILEGES on *.*, privileged',
},
{
dsn => 'DBI:mysql:myDb:myHost:8008',
privileges => [qw/ALTER CREATE INSERT DELETE/],
grants => [
'GRANT ALTER, CREATE, INSERT ON *.* to user@localhost',
],
privileged => 0,
comment => 'Missing DELETE on *.*, unprivileged',
},
{
dsn => 'DBI:mysql:myDb:myHost:8008',
privileges => [qw/ALTER CREATE INSERT DELETE/],
grants => [
'GRANT ALL PRIVILEGES ON myDb.* to user@localhost',
],
privileged => 1,
comment => 'ALL PRIVILEGES on explicit db name, privileged',
},
{
dsn => 'DBI:mysql:myDb:myHost:8008',
privileges => [qw/ALTER CREATE INSERT DELETE/],
grants => [
'GRANT ALL PRIVILEGES ON `myDb`.* to user@localhost',
],
privileged => 1,
comment => 'ALL PRIVILEGES on quoted, explicit db name, privileged',
},
{
dsn => 'DBI:mysql:myDb:myHost:8008',
privileges => [qw/ALTER CREATE INSERT DELETE/],
grants => [
'GRANT ALL PRIVILEGES ON `my%`.* to user@localhost',
],
privileged => 1,
comment => 'ALL PRIVILEGES on quoted, wildcard name, privileged',
},
{
dsn => 'DBI:mysql:yourDb:myHost:8008',
privileges => [qw/ALTER CREATE INSERT DELETE/],
grants => [
'GRANT ALL PRIVILEGES ON `my%`.* to user@localhost',
],
privileged => 0,
comment => 'ALL PRIVILEGES on wrong db, unprivileged',
},
];
plan tests => 2 + scalar @{ $DSNs } + scalar @{ $grants };
my $dbLink = WebGUI::DatabaseLink->new($session, 0);
is($dbLink->get->{DSN}, $session->config->get('dsn'), 'DSN set correctly for default database link');
@ -68,6 +136,15 @@ foreach my $dsn (@{ $DSNs }) {
$dbl->delete;
}
foreach my $grant (@{ $grants }) {
my $dbl = WebGUI::DatabaseLink->create($session, { DSN => $grant->{dsn} });
is(
$dbl->checkPrivileges($grant->{privileges}, $grant->{grants}),
$grant->{privileged},
$grant->{comment}
);
$dbl->delete;
}
END {
foreach my $link ($dbLink, ) {