First attempt at usable privilege granting (MySQL only currently) abandoned/mysql_grant_privileges_sketch
Ash Berlin [Thu, 9 Nov 2006 21:05:14 +0000 (21:05 +0000)]
lib/DBIx/Class/Storage/DBI.pm
lib/DBIx/Class/Storage/DBI/mysql.pm

index a0a34a8..cbcdadb 100644 (file)
@@ -10,6 +10,7 @@ use SQL::Abstract::Limit;
 use DBIx::Class::Storage::DBI::Cursor;
 use DBIx::Class::Storage::Statistics;
 use IO::File;
+use Carp::Clan qw/DBIx::Class/;
 
 __PACKAGE__->mk_group_accessors(
   'simple' =>
@@ -1212,7 +1213,8 @@ sub deploy {
       next if($_ =~ /^COMMIT/m);
       next if $_ =~ /^\s+$/; # skip whitespace only
       $self->debugobj->query_start($_) if $self->debug;
-      $self->dbh->do($_) or warn "SQL was:\n $_"; # XXX exceptions?
+      eval {$self->dbh->do($_) or warn "SQL was:\n $_"}; # XXX exceptions?
+      if ($@) {warn "$@ while executing: $_\n";}
       $self->debugobj->query_end($_) if $self->debug;
     }
   }
@@ -1252,6 +1254,98 @@ sub build_datetime_parser {
   return $type;
 }
 
+=head2 pre_grant
+
+Prefrom any necesassry steps before preforming a GRANT operation. C<$args>
+can be altered if needed.
+
+=over 4
+
+=item Arguments: $args
+
+=item Return: true to continue processing grant operation
+
+=back
+
+=cut
+
+sub pre_grant { 1 };
+
+=head2 post_grant
+
+Prefrom any necesassry steps after a GRANT command has been issued. For 
+example mysql will issue "FLUSH PRIVILEGES"
+
+=cut
+
+sub post_grant {};
+
+=head2 grant_statements
+
+=cut
+
+sub grant_statements {
+    my ($self, $args) = @_;
+
+
+    my $entity = $args->{user} || $args->{group} or croak "Unable to get grant entity";
+
+    my $known_privileges = $self->known_privileges;
+    my @privs = grep { $known_privileges->{$_}  } @{$args->{privileges}};
+
+    my $grant = "GRANT " . join(", ", @privs) . " ON $args->{object} TO $entity";
+
+    my ($user, $password) = @{$args}{qw/user password/};
+    return $user && $password ? ($grant, $self->set_user_password($user, $password)) : ($grant);
+}
+
+=head2 grant
+
+Grant privileges to an entity. This function takes a single hash ref 
+containing the following keys
+
+=over 4
+
+=item user
+
+=item group
+
+These specify the entitiy to grant privileges to. If both are specified 
+C<group> will be ignored.
+
+=item object
+
+The (database specific syntax) object to grant privileges on. For example this
+could be a C<database.table> for a MySQL, or a stored function name in Oracle
+to grant execution rights upon.
+
+=item privileges
+
+An array ref of privileges to grant to entity on object. Currently this is
+database specific, and any unknown privileges are silently ignored.
+
+=back
+
+=cut
+
+sub grant {
+    my ($self, $args) = @_;
+
+    return unless $self->pre_grant($args);
+
+    my @stmts = $self->grant_statements($args);
+
+    foreach (@stmts) {
+        $self->dbh->do($_);
+    }
+
+    $self->post_grant($args);
+}
+
+sub current_schema { shift->throw_exception("DBI did not define current_schema"); }
+
+sub known_privileges { {} };
+
 sub DESTROY {
   my $self = shift;
   return if !$self->_dbh;
index 8ecdfca..01d3e9f 100644 (file)
@@ -16,6 +16,61 @@ sub sqlt_type {
   return 'MySQL';
 }
 
+
+my @table_privileges = (qw/
+    ALTER
+    CREATE
+    DELETE
+    FILE
+    INDEX
+    INSERT
+    SELECT
+    UPDATE
+    USAGE/,
+    'CREATE TEMPORARY TABLE',
+    'LOCK TABLES',
+    'CREATE VIEW');
+
+my @dba_privileges = (
+    'CREATE USER',
+    'DROP',
+    'EVENT',
+    'PROCESS',
+    'RELOAD',
+    'REPLICATION CLIENT',
+    'REPLICATION SLAVE',
+    'SHUTDOWN',
+    'SUPER',
+    'GRANT OPTION',
+    'ALL',
+    'ALL PRIVILEGES');
+
+my @stored_func_privileges = (
+    'ALTER ROUTINE',
+    'CREATE ROUTINE',
+    'EXECUTE',
+    'TRIGGER');
+
+sub known_privileges {
+    return { map { $_ => 1 } @table_privileges, @dba_privileges, @stored_func_privileges };
+}
+
+sub set_user_password {
+    my ($self, $user, $password) = @_;
+
+    return "SET PASSWORD FOR $user = PASSWORD('$password')";
+}
+
+sub current_schema {
+    my ($self) = @_;
+    return $self->dbh->selectrow_arrayref("SELECT DATABASE()")->[0];
+}
+
+sub post_grant {
+    my ($self) = @_;
+    $self->dbh->do('FLUSH PRIVILEGES');
+}
+
 1;
 
 =head1 NAME