Page to save user DB, SQL to create tables
authorJamie Cameron <jcameron@webmin.com>
Tue, 7 Sep 2010 00:13:57 +0000 (17:13 -0700)
committerJamie Cameron <jcameron@webmin.com>
Tue, 7 Sep 2010 00:13:57 +0000 (17:13 -0700)
acl/acl-lib.pl
acl/edit_sql.cgi [new file with mode: 0644]
acl/lang/en
acl/save_sql.cgi [new file with mode: 0755]

index 4735bd4..1f0b89f 100755 (executable)
@@ -1173,9 +1173,9 @@ $miniserv{'anonymous'} = join(" ", @anon);
 sub split_userdb_string
 {
 my ($str) = @_;
-if ($str =~ /^([a-z]+):\/\/([^:]+):([^\@]+)\@([a-z0-9\.\-\_]+)\/([^\?]+)(\?(.*))?$/) {
+if ($str =~ /^([a-z]+):\/\/([^:]*):([^\@]*)\@([a-z0-9\.\-\_]+)\/([^\?]+)(\?(.*))?$/) {
        my ($proto, $user, $pass, $host, $prefix, $argstr) =
-               ($1, $2, $3, $3, $5, $7);
+               ($1, $2, $3, $4, $5, $7);
        my %args = map { split(/=/, $_, 2) } split(/\&/, $argstr);
        return ($proto, $user, $pass, $host, $prefix, \%args);
        }
@@ -1195,11 +1195,11 @@ if (keys %$args) {
 return $proto."://".$user.":".$pass."\@".$host."/".$prefix.$argstr;
 }
 
-# validate_userdb(string)
+# validate_userdb(string, [no-table-check])
 # Checks if some user database is usable, and if not returns an error message
 sub validate_userdb
 {
-my ($str) = @_;
+my ($str, $notablecheck) = @_;
 my ($proto, $user, $pass, $host, $prefix, $args) = &split_userdb_string($str);
 if ($proto eq "mysql" || $proto eq "postgresql") {
        # Load DBI driver
@@ -1223,22 +1223,25 @@ if ($proto eq "mysql" || $proto eq "postgresql") {
        ref($dbh) || return $dbh;
 
        # Validate critical tables
-       my %tables = ( "webmin_user" => [ "id", "name", "pass" ],
-                      "webmin_group" => [ "id", "name", "desc" ],
-                      "webmin_user_attr" => [ "id", "attr", "value" ],
-                      "webmin_group_attr" => [ "id", "attr", "value" ],
-                      "webmin_user_acl" => [ "id", "module", "attr", "value" ],
-                      "webmin_group_acl" => [ "id", "module", "attr", "value"],
-                    );
-       foreach my $t (keys %tables) {
-               my @cols = @{$tables{$t}};
-               my $sql = "select ".join(",", @cols)." from $t limit 1";
-               my $cmd = $dbh->prepare($sql);
-               if (!$cmd || !$cmd->execute()) {
-                       return &text('sql_etable', $t,
-                                    &html_escape($dbh->errstr));
+       if (!$notablecheck) {
+               my %tables =
+                 ( "webmin_user" => [ "id", "name", "pass" ],
+                   "webmin_group" => [ "id", "name", "desc" ],
+                   "webmin_user_attr" => [ "id", "attr", "value" ],
+                   "webmin_group_attr" => [ "id", "attr", "value" ],
+                   "webmin_user_acl" => [ "id", "module", "attr", "value" ],
+                   "webmin_group_acl" => [ "id", "module", "attr", "value"],
+                 );
+               foreach my $t (keys %tables) {
+                       my @cols = @{$tables{$t}};
+                       my $sql = "select ".join(",", @cols)." from $t limit 1";
+                       my $cmd = $dbh->prepare($sql);
+                       if (!$cmd || !$cmd->execute()) {
+                               return &text('sql_etable', $t,
+                                            &html_escape($dbh->errstr));
+                               }
+                       $cmd->finish();
                        }
-               $cmd->finish();
                }
        &disconnect_userdb($str, $dbh);
        return undef;
@@ -1304,5 +1307,19 @@ elsif ($str =~ /^ldap:/) {
        }
 }
 
+# userdb_table_sql(string)
+# Returns SQL statements needed to create all required tables
+sub userdb_table_sql
+{
+my ($str) = @_;
+return ( "create table webmin_user (id int(20), name varchar(255), pass varchar(255))",
+        "create table webmin_group (id init(20), name varchar(255), desc varchar(255))",
+        "create table webmin_user_attr (id int(20), attr varchar(32), value varchar(255))",
+        "create table webmin_group_attr (id int(20), attr varchar(32), value varchar(255))",
+         "create table webmin_user_acl (id int(20), module varchar(32), attr varchar(32), value varchar(255))",
+         "create table webmin_group_acl (id int(20), module varchar(32), attr varchar(32), value varchar(255))",
+        );
+}
+
 1;
 
diff --git a/acl/edit_sql.cgi b/acl/edit_sql.cgi
new file mode 100644 (file)
index 0000000..3e6b6d5
--- /dev/null
@@ -0,0 +1,79 @@
+#!/usr/local/bin/perl
+# Show form for an external user / group database
+
+require './acl-lib.pl';
+$access{'sql'} || &error($text{'sql_ecannot'});
+&ui_print_header(undef, $text{'sql_title'}, "");
+&get_miniserv_config(\%miniserv);
+
+print &ui_form_start("save_sql.cgi");
+print &ui_table_start($text{'sql_header'}, undef, 2);
+
+($proto, $user, $pass, $host, $prefix, $args) =
+       &split_userdb_string($miniserv{'userdb'});
+
+# Build inputs for MySQL backend
+@mysqlgrid = ( );
+push(@mysqlgrid,
+     $text{'sql_host'},
+     &ui_textbox("mysql_host", $proto eq "mysql" ? $host : "", 30));
+push(@mysqlgrid,
+     $text{'sql_user'},
+     &ui_textbox("mysql_user", $proto eq "mysql" ? $user : "", 30));
+push(@mysqlgrid,
+     $text{'sql_pass'},
+     &ui_textbox("mysql_pass", $proto eq "mysql" ? $pass : "", 30));
+push(@mysqlgrid,
+     $text{'sql_db'},
+     &ui_textbox("mysql_db", $proto eq "mysql" ? $prefix : "", 30));
+$mysqlgrid = &ui_grid_table(\@mysqlgrid, 2, 100);
+
+# Build inputs for PostgreSQL backend
+@postgresqlgrid = ( );
+push(@postgresqlgrid,
+     $text{'sql_host'},
+     &ui_textbox("postgresql_host", $proto eq "postgresql" ? $host : "", 30));
+push(@postgresqlgrid,
+     $text{'sql_user'},
+     &ui_textbox("postgresql_user", $proto eq "postgresql" ? $user : "", 30));
+push(@postgresqlgrid,
+     $text{'sql_pass'},
+     &ui_textbox("postgresql_pass", $proto eq "postgresql" ? $pass : "", 30));
+push(@postgresqlgrid,
+     $text{'sql_db'},
+     &ui_textbox("postgresql_db", $proto eq "postgresql" ? $prefix : "", 30));
+$postgresqlgrid = &ui_grid_table(\@postgresqlgrid, 2, 100);
+
+# Build inputs for LDAP backend
+@ldapgrid = ( );
+push(@ldapgrid,
+     $text{'sql_host'},
+     &ui_textbox("ldap_host", $proto eq "ldap" ? $host : "", 30));
+push(@ldapgrid,
+     $text{'sql_user'},
+     &ui_textbox("ldap_user", $proto eq "ldap" ? $user : "", 30));
+push(@ldapgrid,
+     $text{'sql_pass'},
+     &ui_textbox("ldap_pass", $proto eq "ldap" ? $pass : "", 30));
+push(@ldapgrid,
+     $text{'sql_prefix'},
+     &ui_textbox("ldap_prefix", $proto eq "ldap" ? $prefix : "", 30));
+# XXX object classes?
+$ldapgrid = &ui_grid_table(\@ldapgrid, 2, 100);
+
+print &ui_table_row(undef,
+       &ui_radio_table("proto", $proto,
+               [ [ '', $text{'sql_none'} ],
+                 [ 'mysql', $text{'sql_mysql'}, $mysqlgrid ],
+                 [ 'postgresql', $text{'sql_postgresql'}, $postgresqlgrid ],
+                 [ 'ldap', $text{'sql_ldap'}, $ldapgrid ] ]), 2);
+
+print &ui_table_row(undef,
+       &ui_radio("addto", int($miniserv{'userdb_addto'}),
+                 [ [ 0, $text{'sql_addto0'} ],
+                   [ 1, $text{'sql_addto1'} ] ]), 2);
+
+print &ui_table_end();
+print &ui_form_end([ [ undef, $text{'save'} ] ]);
+
+&ui_print_footer("", $text{'index_return'});
index 833763d..8239ec4 100644 (file)
@@ -218,6 +218,7 @@ log_delete_groups=Deleted $1 Webmin groups
 log_pass=Changed password restrictions
 log_unix=Changed unix user authentication
 log_sync=Changed unix user synchronization
+log_sql=Changed user and group database
 
 gedit_ecannot=You are not allowed to edit groups
 gedit_title=Edit Webmin Group
@@ -396,3 +397,14 @@ sql_emysqlconnect=Failed to connect to MySQL database : $1
 sql_epostgresqldriver=Failed to load PostgreSQL DBI driver
 sql_epostgresqlconnect=Failed to connect to PostgreSQL database : $1
 sql_etable=Failed to query required table $1 : $2
+sql_err=Failed to save user and group database settings
+sql_ehost=Missing or un-resolvable hostname
+sql_euser=Missing or invalid username (no spaces allowed)
+sql_epass=Invalid password (no spaces allowed)
+sql_edb=Invalid database name (no spaces allowed)
+sql_eprefix=Missing or invalid base DN (no spaces allowed)
+sql_eprefix2=Invalid-looking base DN - should be like <tt>dc=mydomain,dc=com</tt>
+sql_title2=Create Missing Tables
+sql_tableerr=User and group database settings were successfully saved, but some tables needed by Webmin are missing : $1
+sql_tableerr2=Click the <b>Create Tables</b> to have them created automatically, or manually run the SQL below.
+sql_make=Create Tables
diff --git a/acl/save_sql.cgi b/acl/save_sql.cgi
new file mode 100755 (executable)
index 0000000..2e793df
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/local/bin/perl
+# Save user and group database
+
+require './acl-lib.pl';
+$access{'pass'} || &error($text{'sql_ecannot'});
+&get_miniserv_config(\%miniserv);
+&ReadParse();
+&error_setup($text{'sql_err'});
+$p = $in{'proto'};
+
+# Parse inputs
+if ($p eq 'mysql' || $p eq 'postgresql' || $p eq 'ldap') {
+       gethostbyname($in{$p."_host"}) ||
+         $in{$p."_host"} =~ /^(\S+):(\d+)$/ && gethostbyname($1) ||
+           &error($text{'sql_ehost'});
+       $in{$p."_user"} =~ /^\S+$/ || &error($text{'sql_euser'});
+       $in{$p."_pass"} =~ /^\S*$/ || &error($text{'sql_epass'});
+       $host = $in{$p."_host"};
+       $user = $in{$p."_user"};
+       $pass = $in{$p."_pass"};
+       }
+if ($p eq 'mysql' || $p eq 'postgresql') {
+       $in{$p."_db"} =~ /^\S+$/ || &error($text{'sql_edb'});
+       $prefix = $in{$p."_db"};
+       }
+elsif ($p eq 'ldap') {
+       $in{$p."_prefix"} =~ /^\S+$/ || &error($text{'sql_eprefix'});
+       $in{$p."_prefix"} =~ /=/ || &error($text{'sql_eprefix2'});
+       $prefix = $in{$p."_prefix"};
+       }
+
+# Create and test connection string
+if ($p) {
+       $str = &join_userdb_string($p, $user, $pass, $host,
+                                  $prefix, $args);
+       $err = &validate_userdb($str, 1);
+       &error($err) if ($err);
+       }
+
+&lock_file($ENV{'MINISERV_CONFIG'});
+$miniserv{'userdb'} = $str;
+$miniserv{'userdb_addto'} = $in{'addto'};
+&put_miniserv_config(\%miniserv);
+&unlock_file($ENV{'MINISERV_CONFIG'});
+&reload_miniserv();
+&webmin_log("sql");
+
+# Make sure tables exist
+$err = &validate_userdb($str, 0);
+if ($err) {
+       &ui_print_header(undef, $text{'sql_title2'}, "");
+
+       print &text('sql_tableerr', $err),"<p>\n";
+       print $text{'sql_tableerr2'},"<p>\n";
+       print &ui_form_start("maketables.sql");
+       print &ui_form_end([ [ undef, $text{'sql_make'} ] ]);
+
+       print &ui_table_start(undef, undef, 2);
+       foreach $sql (&userdb_table_sql($str)) {
+               print &ui_table_row(undef,
+                       "<pre>".&html_escape($sql)."</pre>", 2);
+               }
+       print &ui_table_end();
+
+       &ui_print_footer("", $text{'index_return'});
+       }
+else {
+       &redirect("");
+       }
+