Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision f30f0cce

Von Moritz Bunkus vor etwa 7 Jahren hinzugefügt

  • ID f30f0cce6468f895c7d59f3aab6e2a5731fc9705
  • Vorgänger 8085e7b1
  • Nachfolger b08b354b

Datenbankupgrades: Unterstützung für einzelne Updates mit Superuser-Rechten

Setzt man den neuen Tag `@superuser_privileges` auf 1, so schaut
kivitendo vor dem Einspielen aller Upgrades nach, ob der konfigurierte
Datenbankuser Superuser-Rechte hat. Falls nicht, wird die Benutzer*in
nach entsprechenden Logindaten gefragt.

Nur die Upgradescripte, die tatsächlich Superuser-Rechte benötigen,
werden mit diesem User ausgeführt, alle anderen mit den normalen
Rechten, um Besitzer-Wildwuchs bei neu angelegten Objekten zu
vermeiden.

Unterschiede anzeigen:

SL/DBUpgrade2.pm
100 100

  
101 101
    delete @{$control}{qw(depth applied)};
102 102

  
103
    my @unknown_keys = grep { !m{^ (?: depends | description | file | ignore | locales | may_fail | priority | tag ) $}x } keys %{ $control };
103
    my @unknown_keys = grep { !m{^ (?: depends | description | file | ignore | locales | may_fail | priority | superuser_privileges | tag ) $}x } keys %{ $control };
104 104
    if (@unknown_keys) {
105 105
      _control_error($form, $file_name, sprintf($locale->text("Unknown control fields: #1", join(' ', sort({ lc $a cmp lc $b } @unknown_keys)))));
106 106
    }
SL/User.pm
36 36
package User;
37 37

  
38 38
use IO::File;
39
use Fcntl qw(:seek);
39
use List::MoreUtils qw(any);
40 40

  
41 41
use SL::DB;
42 42
#use SL::Auth;
......
103 103
  return %cc;
104 104
}
105 105

  
106
sub _handle_superuser_privileges {
107
  my ($self, $form) = @_;
108

  
109
  if ($form->{database_superuser_username}) {
110
    $::auth->set_session_value("database_superuser_username" => $form->{database_superuser_username}, "database_superuser_password" => $form->{database_superuser_password});
111
  }
112

  
113
  my %dbconnect_form          = %{ $form };
114
  my ($su_user, $su_password) = map { $::auth->get_session_value("database_superuser_$_") } qw(username password);
115

  
116
  if ($su_user) {
117
    $dbconnect_form{dbuser}   = $su_user;
118
    $dbconnect_form{dbpasswd} = $su_password;
119
  }
120

  
121
  dbconnect_vars(\%dbconnect_form, $form->{dbname});
122

  
123
  my %result = (
124
    username => $dbconnect_form{dbuser},
125
    password => $dbconnect_form{dbpasswd},
126
  );
127

  
128
  $::auth->set_session_value("database_superuser_username" => $dbconnect_form{dbuser}, "database_superuser_password" => $dbconnect_form{dbpasswd});
129

  
130
  my $dbh = SL::DBConnect->connect($dbconnect_form{dbconnect}, $dbconnect_form{dbuser}, $dbconnect_form{dbpasswd}, SL::DBConnect->get_options);
131
  return (%result, error => $::locale->text('The credentials (username & password) for connecting database are wrong.')) if !$dbh;
132

  
133
  my ($is_superuser) = $dbh->selectrow_array(qq|SELECT usesuper FROM pg_user WHERE usename = ?|, undef, $dbconnect_form{dbuser});
134

  
135
  $dbh->disconnect;
136

  
137
  return (%result, have_privileges => 1) if $is_superuser;
138
  return (%result)                       if !$su_user; # no error message if credentials weren't set by the user
139
  return (%result, error => $::locale->text('The database user \'#1\' does not have superuser privileges.', $dbconnect_form{dbuser}));
140
}
141

  
106 142
sub login {
107 143
  my ($self, $form) = @_;
108 144

  
......
149 185

  
150 186
  $form->{dbupdate} = "db" . $::auth->client->{dbname};
151 187

  
152
  if ($form->{"show_dbupdate_warning"}) {
153
    print $form->parse_html_template("dbupgrade/warning", { unapplied_scripts => \@unapplied_scripts });
188
  my $show_update_warning = $form->{"show_dbupdate_warning"};
189
  my %superuser           = (need_privileges => (any { $_->{superuser_privileges} } @unapplied_scripts));
190

  
191
  if ($superuser{need_privileges}) {
192
    %superuser = (
193
      %superuser,
194
      $self->_handle_superuser_privileges($form),
195
    );
196
    $show_update_warning = 1 if !$superuser{have_privileges};
197
  }
198

  
199
  if ($show_update_warning) {
200
    print $form->parse_html_template("dbupgrade/warning", {
201
      unapplied_scripts => \@unapplied_scripts,
202
      superuser         => \%superuser,
203
    });
154 204
    $::dispatcher->end_request;
155 205
  }
156 206

  
......
442 492
  $self->create_schema_info_table($form, $dbh);
443 493

  
444 494
  my @upgradescripts = $dbupdater->unapplied_upgrade_scripts($dbh);
495
  my $need_superuser = (any { $_->{superuser_privileges} } @upgradescripts);
496
  my $superuser_dbh;
497

  
498
  if ($need_superuser) {
499
    my %dbconnect_form = (
500
      %{ $form },
501
      dbuser   => $::auth->get_session_value("database_superuser_username"),
502
      dbpasswd => $::auth->get_session_value("database_superuser_password"),
503
    );
504

  
505
    if ($dbconnect_form{dbuser} ne $form->{dbuser}) {
506
      dbconnect_vars(\%dbconnect_form, $db);
507
      $superuser_dbh = SL::DBConnect->connect($dbconnect_form{dbconnect}, $dbconnect_form{dbuser}, $dbconnect_form{dbpasswd}, SL::DBConnect->get_options) or $form->dberror;
508
    }
509
  }
445 510

  
446 511
  $::lxdebug->log_time("DB upgrades commencing");
447 512

  
......
449 514
    # Apply upgrade. Control will only return to us if the upgrade has
450 515
    # been applied correctly and if the update has not requested user
451 516
    # interaction.
452
    $main::lxdebug->message(LXDebug->DEBUG2(), "Applying Update $control->{file}");
517
    my $script_dbh = $control->{superuser_privileges} ? ($superuser_dbh // $dbh) : $dbh;
518

  
519
    $::lxdebug->message(LXDebug->DEBUG2(), "Applying Update $control->{file}" . ($control->{superuser_privileges} ? " with superuser privileges" : ""));
453 520
    print $form->parse_html_template("dbupgrade/upgrade_message2", $control) unless $silent;
454 521

  
455
    $dbupdater->process_file($dbh, "sql/Pg-upgrade2/$control->{file}", $control);
522
    $dbupdater->process_file($script_dbh, "sql/Pg-upgrade2/$control->{file}", $control);
456 523
  }
457 524

  
458 525
  $::lxdebug->log_time("DB upgrades finished");
459 526

  
460 527
  $dbh->disconnect;
528
  $superuser_dbh->disconnect if $superuser_dbh;
461 529
}
462 530

  
463 531
sub data {
locale/de/all
852 852
  'Database login (#1)'         => 'Datenbankanmeldung (#1)',
853 853
  'Database name'               => 'Datenbankname',
854 854
  'Database settings'           => 'Datenbankeinstellungen',
855
  'Database superuser privileges are required for the update.' => 'Datenbank-Super-Benutzer-Rechte werden für das Update benötigt.',
855 856
  'Database template'           => 'Datenbankvorlage',
856 857
  'Database update error:'      => 'Fehler beim Datenbankupgrade:',
857 858
  'Database user and password'  => 'Datenbankbenutzer und -passwort',
......
1222 1223
  'Error when saving: #1'       => 'Fehler beim Speichern: #1',
1223 1224
  'Error with default taxzone'  => 'Ungültige Standardsteuerzone',
1224 1225
  'Error!'                      => 'Fehler!',
1226
  'Error: #1'                   => 'Fehler: #1',
1225 1227
  'Error: A negative target quantity is not allowed.' => 'Fehler: Eine negative Zielmenge ist nicht erlaubt.',
1226 1228
  'Error: A quantity and a target quantity could not be given both.' => 'Fehler: Menge und Zielmenge können nicht beide angegeben werden.',
1227 1229
  'Error: A quantity or a target quantity must be given.' => 'Fehler: Menge oder Zielmenge muss angegeben werden.',
......
2237 2239
  'Please install the below listed modules or ask your system administrator to.' => 'Bitte installieren Sie die unten aufgeführten Module, oder bitten Sie Ihren Administrator darum.',
2238 2240
  'Please log in to the administration panel.' => 'Bitte melden Sie sich im Administrationsbereich an.',
2239 2241
  'Please modify filename'      => 'Bitte Dateinamen editieren',
2242
  'Please provide corresponding credentials.' => 'Bitte geben Sie entsprechende Logindaten an.',
2240 2243
  'Please re-run the analysis for broken general ledger entries by clicking this button:' => 'Bitte wiederholen Sie die Analyse der Hauptbucheinträge, indem Sie auf diesen Button klicken:',
2241 2244
  'Please read the file'        => 'Bitte lesen Sie die Datei',
2242 2245
  'Please select a customer from the list below.' => 'Bitte einen Endkunden aus der Liste auswählen',
......
3108 3111
  'The connection was established successfully.' => 'Die Verbindung zur Datenbank wurde erfolgreich hergestellt.',
3109 3112
  'The contact person attribute "birthday" is converted from a free-form text field into a date field.' => 'Das Kontaktpersonenfeld "Geburtstag" wird von einem freien Textfeld auf ein Datumsfeld umgestellt.',
3110 3113
  'The creation of the authentication database failed:' => 'Das Anlegen der Authentifizierungsdatenbank schlug fehl:',
3114
  'The credentials (username & password) for connecting database are wrong.' => 'Die Daten (Benutzername & Passwort) für das Login zur Datenbank sind falsch.',
3111 3115
  'The custom variable has been created.' => 'Die benutzerdefinierte Variable wurde erfasst.',
3112 3116
  'The custom variable has been deleted.' => 'Die benutzerdefinierte Variable wurde gelöscht.',
3113 3117
  'The custom variable has been saved.' => 'Die benutzerdefinierte Variable wurde gespeichert.',
......
3118 3122
  'The database name is missing.' => 'Der Datenbankname fehlt.',
3119 3123
  'The database port is missing.' => 'Der Datenbankport fehlt.',
3120 3124
  'The database update/creation did not succeed. The file #1 contained the following error:' => 'Die Datenbankaktualisierung/erstellung schlug fehl. Die Datei #1 enthielt den folgenden Fehler:',
3125
  'The database user \'#1\' does not have superuser privileges.' => 'Der Datenbankbenutzer »#1« hat keine Super-Benutzer-Rechte.',
3121 3126
  'The database user is missing.' => 'Der Datenbankbenutzer fehlt.',
3122 3127
  'The dataset #1 has been created.' => 'Die Datenbank #1 wurde angelegt.',
3123 3128
  'The dataset #1 has been deleted.' => 'Die Datenbank #1 wurde gelöscht.',
templates/webpages/dbupgrade/warning.html
1 1
[%- USE T8 %]
2 2
[%- USE HTML %]
3
[%- USE LxERP %]
3
[%- USE LxERP %][%- USE L -%]
4 4
<form name="Form" method="post" action="controller.pl">
5 5

  
6 6
 <input type="hidden" name="action" value="LoginScreen/login">
......
8 8
 <p class="message_hint">
9 9
  [% LxERP.t8('kivitendo is about to update the database [ #1 ].', dbname) | html %]
10 10
 </p>
11

  
12
 [% IF superuser.need_privileges && !superuser.have_privileges %]
13
  <p>
14
   [% LxERP.t8("Database superuser privileges are required for the update.") %]
15
   [% LxERP.t8("Please provide corresponding credentials.") %]
16
  </p>
17

  
18
  [% IF superuser.error %]
19
   <p>[% LxERP.t8("Error: #1", superuser.error) %]</p>
20
  [% END %]
21

  
22
  <table border="0">
23
   <tr>
24
    <td>[% LxERP.t8("User name") %]:</td>
25
    <td>[% L.input_tag("database_superuser_username", superuser.username) %]</td>
26
   </tr>
27

  
28
   <tr>
29
    <td>[% LxERP.t8("Password") %]:</td>
30
    <td>[% L.input_tag("database_superuser_password", superuser.password, type="password") %]</td>
31
   </tr>
32
  </table>
33
 [% END %]
34

  
11 35
 <p>
12 36
  [% 'You should create a backup of the database before proceeding because the backup might not be reversible.' | $T8 %]
13 37
 </p>

Auch abrufbar als: Unified diff