]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 351983: Move admin creation out of checksetup.pl and into Bugzilla::Install
authormkanat%bugzilla.org <>
Sun, 10 Sep 2006 09:27:35 +0000 (09:27 +0000)
committermkanat%bugzilla.org <>
Sun, 10 Sep 2006 09:27:35 +0000 (09:27 +0000)
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> (module owner) a=justdave

Bugzilla/Install.pm
checksetup.pl
template/en/default/global/messages.html.tmpl

index d8fc478941ee56ffdf511a9af57c3fb9e8466e44..43981da02ddb5339fd1d3018d989f4a31c224858 100644 (file)
@@ -26,8 +26,11 @@ package Bugzilla::Install;
 
 use strict;
 
+use Bugzilla::Constants;
+use Bugzilla::Error;
 use Bugzilla::Group;
 use Bugzilla::Product;
+use Bugzilla::User;
 use Bugzilla::User::Setting;
 use Bugzilla::Version;
 
@@ -136,6 +139,128 @@ sub create_default_product {
 
 }
 
+sub create_admin {
+    my ($params) = @_;
+    my $dbh      = Bugzilla->dbh;
+    my $template = Bugzilla->template;
+
+    my $admin_group = new Bugzilla::Group({ name => 'admin' });
+    my $admin_inheritors = 
+        Bugzilla::User->flatten_group_membership($admin_group->id);
+    my $admin_group_ids = join(',', @$admin_inheritors);
+
+    my ($admin_count) = $dbh->selectrow_array(
+        "SELECT COUNT(*) FROM user_group_map 
+          WHERE group_id IN ($admin_group_ids)");
+
+    return if $admin_count;
+
+    my %answer    = %{$params->{answer} || {}};
+    my $login     = $answer{'ADMIN_EMAIL'};
+    my $password  = $answer{'ADMIN_PASSWORD'};
+    my $full_name = $answer{'ADMIN_REALNAME'};
+
+    if (!$login || !$password || !$full_name) {
+        print "\n" . get_text('install_admin_setup') . "\n\n";
+    }
+
+    while (!$login) {
+        print get_text('install_admin_get_email') . ' ';
+        $login = <STDIN>;
+        chomp $login;
+        eval { Bugzilla::User->check_login_name_for_creation($login); };
+        if ($@) {
+            print $@ . "\n";
+            undef $login;
+        }
+    }
+
+    while (!defined $full_name) {
+        print get_text('install_admin_get_name') . ' ';
+        $full_name = <STDIN>;
+        chomp($full_name);
+    }
+
+    while (!$password) {
+        # trap a few interrupts so we can fix the echo if we get aborted.
+        local $SIG{HUP}  = \&_create_admin_exit;
+        local $SIG{INT}  = \&_create_admin_exit;
+        local $SIG{QUIT} = \&_create_admin_exit;
+        local $SIG{TERM} = \&_create_admin_exit;
+
+        system("stty","-echo") unless ON_WINDOWS;  # disable input echoing
+
+        print get_text('install_admin_get_password') . ' ';
+        $password = <STDIN>;
+        print "\n", get_text('install_admin_get_password2') . ' ';
+        my $pass2 = <STDIN>;
+        eval { validate_password($password, $pass2); };
+        if ($@) {
+            print "\n$@\n";
+            undef $password;
+        }
+        system("stty","echo") unless ON_WINDOWS;
+    }
+
+    my $admin = Bugzilla::User->create({ login_name    => $login, 
+                                         realname      => $full_name,
+                                         cryptpassword => $password });
+    make_admin($admin);
+}
+
+sub make_admin {
+    my ($user) = @_;
+    my $dbh = Bugzilla->dbh;
+
+    $user = ref($user) ? $user 
+            : new Bugzilla::User(login_to_id($user, THROW_ERROR));
+
+    my $admin_group = new Bugzilla::Group({ name => 'admin' });
+
+    # Admins get explicit membership and bless capability for the admin group
+    $dbh->selectrow_array("SELECT id FROM groups WHERE name = 'admin'");
+
+    my $group_insert = $dbh->prepare(
+        'INSERT INTO user_group_map (user_id, group_id, isbless, grant_type)
+              VALUES (?, ?, ?, ?)');
+    # These are run in an eval so that we can ignore the error of somebody
+    # already being granted these things.
+    eval { 
+        $group_insert->execute($user->id, $admin_group->id, 0, GRANT_DIRECT); 
+    };
+    eval {
+        $group_insert->execute($user->id, $admin_group->id, 1, GRANT_DIRECT);
+    };
+
+    # Admins should also have editusers directly, even though they'll usually
+    # inherit it. People could have changed their inheritance structure.
+    my $editusers = new Bugzilla::Group({ name => 'editusers' });
+    eval { 
+        $group_insert->execute($user->id, $editusers->id, 0, GRANT_DIRECT); 
+    };
+
+    print "\n", get_text('install_admin_created', { user => $user }), "\n";
+}
+
+# This is just in case we get interrupted while getting the admin's password.
+sub _create_admin_exit {
+    # re-enable input echoing
+    system("stty","echo") unless ON_WINDOWS;
+    exit 1;
+}
+
+sub get_text {
+    my ($name, $vars) = @_;
+    my $template = Bugzilla->template;
+    $vars ||= {};
+    $vars->{'message'} = $name;
+    my $message;
+    $template->process('global/message.txt.tmpl', $vars, \$message)
+        || ThrowTemplateError($template->error());
+    $message =~ s/^\s+//gm;
+    return $message;
+}
+
 1;
 
 __END__
index 27ee5d6eaee771325c920d8f618a27fbaafa0690..169ccb652db1623454fea7cd4fdf1a57637178de 100755 (executable)
@@ -44,6 +44,7 @@ checksetup.pl - A do-it-all upgrade and installation script for Bugzilla.
 
  ./checksetup.pl [--help|--check-modules]
  ./checksetup.pl [SCRIPT [--verbose]] [--no-templates|-t]
+ ./checksetup.pl --make-admin=user@domain.com
 
 =head1 OPTIONS
 
@@ -65,6 +66,12 @@ Display this help text
 
 Only check for correct module dependencies and quit afterward.
 
+=item B<--make-admin>=username@domain.com
+
+Makes the specified user into a Bugzilla administrator. This is
+in case you accidentally lock yourself out of the Bugzilla administrative
+interface.
+
 =item B<--no-templates> (B<-t>) 
 
 Don't compile the templates at all. Existing compiled templates will 
@@ -204,7 +211,6 @@ The format of that file is as follows:
 
  (Any localconfig variable or parameter can be specified as above.)
 
- $answer{'ADMIN_OK'} = 'Y';
  $answer{'ADMIN_EMAIL'} = 'myadmin@mydomain.net';
  $answer{'ADMIN_PASSWORD'} = 'fooey';
  $answer{'ADMIN_REALNAME'} = 'Joel Peshkin';
@@ -270,7 +276,7 @@ sub read_answers_file {
 
 my %switch;
 GetOptions(\%switch, 'help|h|?', 'check-modules', 'no-templates|t',
-                     'verbose|v|no-silent');
+                     'verbose|v|no-silent', 'make-admin=s');
 
 # Print the help message if that switch was selected.
 pod2usage({-verbose => 1, -exitval => 1}) if $switch{'help'};
@@ -343,6 +349,8 @@ require Bugzilla::Template;
 require Bugzilla::Field;
 require Bugzilla::Install;
 
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
 ###########################################################################
 # Check and update --LOCAL-- configuration
 ###########################################################################
@@ -585,215 +593,8 @@ Bugzilla::Install::update_settings();
 # Create Administrator  --ADMIN--
 ###########################################################################
 
-sub bailout {   # this is just in case we get interrupted while getting passwd
-    if ($^O !~ /MSWin32/i) {
-        system("stty","echo"); # re-enable input echoing
-    }
-    exit 1;
-}
-
-my @groups = ();
-$sth = $dbh->prepare("SELECT id FROM groups");
-$sth->execute();
-while ( my @row = $sth->fetchrow_array() ) {
-    push (@groups, $row[0]);
-}
-
-#  Prompt the user for the email address and name of an administrator.  Create
-#  that login, if it doesn't exist already, and make it a member of all groups.
-
-$sth = $dbh->prepare("SELECT user_id FROM groups INNER JOIN user_group_map " .
-                     "ON id = group_id WHERE name = 'admin'");
-$sth->execute;
-# when we have no admin users, prompt for admin email address and password ...
-if ($sth->rows == 0) {
-    my $login = "";
-    my $realname = "";
-    my $pass1 = "";
-    my $pass2 = "*";
-    my $admin_ok = 0;
-    my $admin_create = 1;
-    my $mailcheckexp = "";
-    my $mailcheck    = ""; 
-
-    # Here we look to see what the emailregexp is set to so we can 
-    # check the email address they enter. Bug 96675. If they have no 
-    # params (likely but not always the case), we use the default.
-    if (-e "$datadir/params") { 
-        require "$datadir/params"; # if they have a params file, use that
-    }
-    if (Bugzilla->params->{'emailregexp'}) {
-        $mailcheckexp = Bugzilla->params->{'emailregexp'};
-        $mailcheck    = Bugzilla->params->{'emailregexpdesc'};
-    } else {
-        $mailcheckexp = '^[\\w\\.\\+\\-=]+@[\\w\\.\\-]+\\.[\\w\\-]+$';
-        $mailcheck    = 'A legal address must contain exactly one \'@\', 
-        and at least one \'.\' after the @.';
-    }
-
-    print "\nLooks like we don't have an administrator set up yet.\n";
-    print "Either this is your first time using Bugzilla, or your\n ";
-    print "administrator's privileges might have accidentally been deleted.\n";
-    while(! $admin_ok ) {
-        while( $login eq "" ) {
-            print "Enter the e-mail address of the administrator: ";
-            $login = $answer{'ADMIN_EMAIL'} 
-                || ($silent && die("cant preload ADMIN_EMAIL")) 
-                || <STDIN>;
-            chomp $login;
-            if(! $login ) {
-                print "\nYou DO want an administrator, don't you?\n";
-            }
-            unless ($login =~ /$mailcheckexp/) {
-                print "\nThe login address is invalid:\n";
-                print "$mailcheck\n";
-                print "You can change this test on the params page once checksetup has successfully\n";
-                print "completed.\n\n";
-                # Go round, and ask them again
-                $login = "";
-            }
-        }
-        $sth = $dbh->prepare("SELECT login_name FROM profiles " .
-                              "WHERE " . $dbh->sql_istrcmp('login_name', '?'));
-        $sth->execute($login);
-        if ($sth->rows > 0) {
-            print "$login already has an account.\n";
-            print "Make this user the administrator? [Y/n] ";
-            my $ok = $answer{'ADMIN_OK'} 
-                || ($silent && die("cant preload ADMIN_OK")) 
-                || <STDIN>;
-            chomp $ok;
-            if ($ok !~ /^n/i) {
-                $admin_ok = 1;
-                $admin_create = 0;
-            } else {
-                print "OK, well, someone has to be the administrator.\n";
-                print "Try someone else.\n";
-                $login = "";
-            }
-        } else {
-            print "You entered $login.  Is this correct? [Y/n] ";
-            my $ok = $answer{'ADMIN_OK'} 
-                || ($silent && die("cant preload ADMIN_OK")) 
-                || <STDIN>;
-            chomp $ok;
-            if ($ok !~ /^n/i) {
-                $admin_ok = 1;
-            } else {
-                print "That's okay, typos happen.  Give it another shot.\n";
-                $login = "";
-            }
-        }
-    }
-
-    if ($admin_create) {
-        while( $realname eq "" ) {
-            print "Enter the real name of the administrator: ";
-            $realname = $answer{'ADMIN_REALNAME'} 
-                || ($silent && die("cant preload ADMIN_REALNAME")) 
-                || <STDIN>;
-            chomp $realname;
-            if(! $realname ) {
-                print "\nReally.  We need a full name.\n";
-            }
-            if(! is_7bit_clean($realname)) {
-                print "\nSorry, but at this stage the real name can only " . 
-                      "contain standard English\ncharacters.  Once Bugzilla " .
-                      "has been installed, you can use the 'Prefs' page\nto " .
-                      "update the real name.\n";
-                $realname = '';
-            }
-        }
-
-        # trap a few interrupts so we can fix the echo if we get aborted.
-        $SIG{HUP}  = \&bailout;
-        $SIG{INT}  = \&bailout;
-        $SIG{QUIT} = \&bailout;
-        $SIG{TERM} = \&bailout;
-
-        if ($^O !~ /MSWin32/i) {
-            system("stty","-echo");  # disable input echoing
-        }
-
-        while( $pass1 ne $pass2 ) {
-            while( $pass1 eq "" || $pass1 !~ /^[[:print:]]{3,16}$/ ) {
-                print "Enter a password for the administrator account: ";
-                $pass1 = $answer{'ADMIN_PASSWORD'} 
-                    || ($silent && die("cant preload ADMIN_PASSWORD")) 
-                    || <STDIN>;
-                chomp $pass1;
-                if(! $pass1 ) {
-                    print "\n\nAn empty password is a security risk. Try again!\n";
-                } elsif ( $pass1 !~ /^.{3,16}$/ ) {
-                    print "\n\nThe password must be 3-16 characters in length.\n";
-                } elsif ( $pass1 !~ /^[[:print:]]{3,16}$/ ) {
-                    print "\n\nThe password contains non-printable characters.\n";
-                }
-            }
-            print "\nPlease retype the password to verify: ";
-            $pass2 = $answer{'ADMIN_PASSWORD'} 
-                || ($silent && die("cant preload ADMIN_PASSWORD")) 
-                || <STDIN>;
-            chomp $pass2;
-            if ($pass1 ne $pass2) {
-                print "\n\nPasswords don't match.  Try again!\n";
-                $pass1 = "";
-                $pass2 = "*";
-            }
-        }
-
-        if ($^O !~ /MSWin32/i) {
-            system("stty","echo"); # re-enable input echoing
-        }
-
-        $SIG{HUP}  = 'DEFAULT'; # and remove our interrupt hooks
-        $SIG{INT}  = 'DEFAULT';
-        $SIG{QUIT} = 'DEFAULT';
-        $SIG{TERM} = 'DEFAULT';
-
-        Bugzilla::User->create({
-            login_name => $login, 
-            realname   => $realname, 
-            cryptpassword => $pass1});
-    }
-
-    # Put the admin in each group if not already    
-    my $userid = $dbh->selectrow_array("SELECT userid FROM profiles WHERE " .
-                                       $dbh->sql_istrcmp('login_name', '?'),
-                                       undef, $login);
-
-    # Admins get explicit membership and bless capability for the admin group
-    my ($admingroupid) = $dbh->selectrow_array("SELECT id FROM groups 
-                                                WHERE name = 'admin'");
-    $dbh->do("INSERT INTO user_group_map 
-        (user_id, group_id, isbless, grant_type) 
-        VALUES ($userid, $admingroupid, 0, " . GRANT_DIRECT . ")");
-    $dbh->do("INSERT INTO user_group_map 
-        (user_id, group_id, isbless, grant_type) 
-        VALUES ($userid, $admingroupid, 1, " . GRANT_DIRECT . ")");
-
-    # Admins get inherited membership and bless capability for all groups
-    foreach my $group ( @groups ) {
-        my $sth_check = $dbh->prepare("SELECT member_id FROM group_group_map
-                                 WHERE member_id = ?
-                                 AND  grantor_id = ?
-                                 AND grant_type = ?");
-        $sth_check->execute($admingroupid, $group, GROUP_MEMBERSHIP);
-        unless ($sth_check->rows) {
-            $dbh->do("INSERT INTO group_group_map
-                      (member_id, grantor_id, grant_type)
-                      VALUES ($admingroupid, $group, " . GROUP_MEMBERSHIP . ")");
-        }
-        $sth_check->execute($admingroupid, $group, GROUP_BLESS);
-        unless ($sth_check->rows) {
-            $dbh->do("INSERT INTO group_group_map
-                      (member_id, grantor_id, grant_type)
-                      VALUES ($admingroupid, $group, " . GROUP_BLESS . ")");
-        }
-    }
-
-    print "\n$login is now set up as an administrator account.\n";
-}
+Bugzilla::Install::make_admin($switch{'make-admin'}) if $switch{'make-admin'};
+Bugzilla::Install::create_admin({ answer => \%answer });
 
 ###########################################################################
 # Create default Product and Classification
@@ -805,14 +606,6 @@ Bugzilla::Install::create_default_product();
 # Final checks
 ###########################################################################
 
-$sth = $dbh->prepare("SELECT user_id " .
-                       "FROM groups INNER JOIN user_group_map " .
-                       "ON groups.id = user_group_map.group_id " .
-                      "WHERE groups.name = 'admin'");
-$sth->execute;
-my ($adminuid) = $sth->fetchrow_array;
-if (!$adminuid) { die "No administrator!" } # should never get here
-
 # Check if the default parameter for urlbase is still set, and if so, give
 # notification that they should go and visit editparams.cgi 
 
index 4a7c4591c1ed3d0bd2bb80a2e7d3602ea153dc49..0967918050e226bd247389025b5b86b7942117fb 100644 (file)
       <a href="editflagtypes.cgi">Back to flag types.</a>
     </p>
     
+  [% ELSIF message_tag == "install_admin_get_email" %]
+    Enter the e-mail address of the administrator:
+
+  [% ELSIF message_tag == "install_admin_get_name" %]
+    Enter the real name of the administrator:
+
+  [% ELSIF message_tag == "install_admin_get_password" %]
+    Enter a password for the administrator account:
+
+  [% ELSIF message_tag == "install_admin_get_password2" %]
+    Please retype the password to verify:
+
+  [% ELSIF message_tag == "install_admin_created" %]
+    [% user.login FILTER html %] is now set up as an administrator.
+
+  [% ELSIF message_tag == "install_admin_setup" %]
+    Looks like we don't have an administrator set up yet.
+    Either this is your first time using Bugzilla, or your
+    administrator's privileges might have accidentally been deleted.
+
   [% ELSIF message_tag == "product_invalid" %]
     [% title = "$terms.Bugzilla Component Descriptions" %]
     The product <em>[% product FILTER html %]</em> does not exist