Revision f30f0cce
Von Moritz Bunkus vor etwa 7 Jahren hinzugefügt
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
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.