From 66c08b6472a2467444192dbfed35e9f30f7c910d Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Wed, 12 Jun 2013 16:33:09 +0200 Subject: [PATCH] Locking in eigenes Modul verschieben --- SL/Controller/Admin.pm | 21 +++---- SL/DBUpgrade2.pm | 12 ++-- SL/Dispatcher.pm | 2 +- SL/System/InstallationLock.pm | 106 ++++++++++++++++++++++++++++++++++ SL/User.pm | 14 +---- locale/de/all | 7 ++- 6 files changed, 129 insertions(+), 33 deletions(-) create mode 100644 SL/System/InstallationLock.pm diff --git a/SL/Controller/Admin.pm b/SL/Controller/Admin.pm index 8ba249034..c1b2ec1e8 100644 --- a/SL/Controller/Admin.pm +++ b/SL/Controller/Admin.pm @@ -12,11 +12,12 @@ use SL::DB::AuthGroup; use SL::DB::Printer; use SL::Helper::Flash; use SL::Locale::String qw(t8); +use SL::System::InstallationLock; use SL::User; use Rose::Object::MakeMethods::Generic ( - 'scalar --get_set_init' => [ qw(client user group printer nologin_file_name db_cfg is_locked + 'scalar --get_set_init' => [ qw(client user group printer db_cfg is_locked all_dateformats all_numberformats all_countrycodes all_stylesheets all_menustyles all_clients all_groups all_users all_rights all_printers) ], ); @@ -355,7 +356,8 @@ sub action_delete_printer { sub action_unlock_system { my ($self) = @_; - unlink $self->nologin_file_name; + + SL::System::InstallationLock->unlock; flash_later('info', t8('Lockfile removed!')); $self->redirect_to(action => 'show'); } @@ -363,15 +365,9 @@ sub action_unlock_system { sub action_lock_system { my ($self) = @_; - my $fh = IO::File->new($self->nologin_file_name, "w"); - if (!$fh) { - $::form->error(t8('Cannot create Lock!')); - - } else { - $fh->close; - flash_later('info', t8('Lockfile created!')); - $self->redirect_to(action => 'show'); - } + SL::System::InstallationLock->unlock; + flash_later('info', t8('Lockfile created!')); + $self->redirect_to(action => 'show'); } # @@ -379,8 +375,7 @@ sub action_lock_system { # sub init_db_cfg { $::lx_office_conf{'authentication/database'} } -sub init_nologin_file_name { $::lx_office_conf{paths}->{userspath} . '/nologin'; } -sub init_is_locked { -e $_[0]->nologin_file_name } +sub init_is_locked { SL::System::InstallationLock->is_locked } sub init_client { SL::DB::Manager::AuthClient->find_by(id => ($::form->{id} || ($::form->{client} || {})->{id})) } sub init_user { SL::DB::AuthUser ->new(id => ($::form->{id} || ($::form->{user} || {})->{id}))->load } sub init_group { SL::DB::AuthGroup ->new(id => ($::form->{id} || ($::form->{group} || {})->{id}))->load } diff --git a/SL/DBUpgrade2.pm b/SL/DBUpgrade2.pm index 0daec3606..cdfca9b74 100644 --- a/SL/DBUpgrade2.pm +++ b/SL/DBUpgrade2.pm @@ -235,8 +235,8 @@ sub process_query { # Process a Perl script which updates the database. # If the script returns 1 then the update was successful. -# Return code "2" means "needs more interaction; remove -# users/nologin and end current request". +# Return code "2" means "needs more interaction; unlock +# the system and end current request". # All other return codes are fatal errors. sub process_perl_script { $::lxdebug->enter_sub(); @@ -266,7 +266,7 @@ sub process_perl_script { print $::form->parse_html_template("dbupgrade/error", { file => $filename, error => $error }); ::end_of_request(); } elsif (1 != $result) { - unlink("users/nologin") if (2 == $result); + SL::System::InstallationLock->unlock if 2 == $result; ::end_of_request(); } @@ -469,7 +469,9 @@ C) form => $::form, auth => 1 ); - User->dbupdate2($form, $scripts->parse_dbupdate_controls); + User->dbupdate2(form => $form, + updater => $scripts->parse_dbupdate_controls, + database => $dbname); =head1 OVERVIEW @@ -638,7 +640,7 @@ charset recoding of the script if required, C<$db_charset>). Perl scripts are executed via L. If L returns falsish then an error is expected. There are two special return values: If the script returns C<1> then the update was successful. Return code C<2> -means "needs more interaction from the user; remove users/nologin and +means "needs more interaction from the user; unlock the system and end current upgrade process". All other return codes are fatal errors. Inside the Perl script several local variables exist that can be used: diff --git a/SL/Dispatcher.pm b/SL/Dispatcher.pm index 4b25ca749..8329c5b75 100644 --- a/SL/Dispatcher.pm +++ b/SL/Dispatcher.pm @@ -235,7 +235,7 @@ sub handle_request { eval { pre_request_checks(script => $script, action => $action, routing_type => $routing_type, script_name => $script_name); - if ( (-e ($::lx_office_conf{paths}->{userspath} . "/nologin")) + if ( SL::System::InstallationLock->is_locked && !is_admin_request(script => $script, script_name => $script_name, routing_type => $routing_type)) { $::form->error($::locale->text('System currently down for maintenance!')); } diff --git a/SL/System/InstallationLock.pm b/SL/System/InstallationLock.pm new file mode 100644 index 000000000..5020b5e17 --- /dev/null +++ b/SL/System/InstallationLock.pm @@ -0,0 +1,106 @@ +package SL::System::InstallationLock; + +use strict; + +sub lock { + my ($class) = @_; + + return 1 if $::lx_office_conf{debug}->{keep_installation_unlocked}; + + my $fh; + if (!open($fh, ">", $class->lock_file_name)) { + die $::locale->text('Lock file handling failed. Please verify that the directory "#1" is writeable by the webserver.', $::lx_office_conf{paths}->{userspath}); + } + + close $fh; + + return 1; +} + +sub unlock { + my ($class) = @_; + + return 1 if $::lx_office_conf{debug}->{keep_installation_unlocked}; + + my $name = $class->lock_file_name; + if ((-f $name) && !unlink($name)) { + die $::locale->text('Lock file handling failed. Please verify that the directory "#1" is writeable by the webserver.', $::lx_office_conf{paths}->{userspath}); + } + + return 1; +} + +sub is_locked { + my ($class) = @_; + + return 0 if $::lx_office_conf{debug}->{keep_installation_unlocked}; + return -f $class->lock_file_name; +} + +sub lock_file_name { + $::lx_office_conf{paths}->{userspath} . "/nologin"; +} + +1; + +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::System::InstallationLock - Handle locking the installation with a +global lock file + +=head1 SYNOPSIS + + SL::System::InstallationLock->lock; + # Do important and uninterruptable work! + SL::System::InstallationLock->unlock; + + +=head1 OVERVIEW + +If the global lock file exists then no user may login. The +administration area is not affected. + +There's a configuration setting +C. If it is trueish then all of +these commands will always keep the installation unlocked: L +and L won't do anything and L always returns 0. + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns 1 or 0 depending on whether or not the installation is currently locked. + +=item C + +Creates the lock file. Throws an exception if writing to the lock file +location fails. + +=item C + +Returns the file name for the global lock file. + +=item C + +Removed the lock file. Throws an exception if the lock exists and +removing the lock file fails. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/User.pm b/SL/User.pm index ae4c3edef..294a1a3b4 100644 --- a/SL/User.pm +++ b/SL/User.pm @@ -43,6 +43,7 @@ use SL::DBUpgrade2; use SL::DBUtils; use SL::Iconv; use SL::Inifile; +use SL::System::InstallationLock; use strict; @@ -135,13 +136,7 @@ sub login { } # update the tables - my $fh; - if (!$::lx_office_conf{debug}->{keep_installation_unlocked} && !open($fh, ">", $::lx_office_conf{paths}->{userspath} . "/nologin")) { - $form->show_generic_error($main::locale->text('A temporary file could not be created. ' . - 'Please verify that the directory "#1" is writeable by the webserver.', - $::lx_office_conf{paths}->{userspath}), - 'back_button' => 1); - } + SL::System::InstallationLock->lock; # ignore HUP, QUIT in case the webserver times out $SIG{HUP} = 'IGNORE'; @@ -151,10 +146,7 @@ sub login { $self->dbupdate2($form, $dbupdater); SL::DBUpgrade2->new(form => $::form, auth => 1)->apply_admin_dbupgrade_scripts(0); - close($fh); - - # remove lock file - unlink($::lx_office_conf{paths}->{userspath} . "/nologin"); + SL::System::InstallationLock->unlock; print $form->parse_html_template("dbupgrade/footer"); diff --git a/locale/de/all b/locale/de/all index 87ddf8e30..f7481b348 100755 --- a/locale/de/all +++ b/locale/de/all @@ -46,7 +46,6 @@ $self->{texts} = { 'A lower-case character is required.' => 'Ein Kleinbuchstabe ist vorgeschrieben.', 'A special character is required (valid characters: #1).' => 'Ein Sonderzeichen ist vorgeschrieben (gültige Zeichen: #1).', 'A temporary directory could not be created:' => 'Ein temporäres Verzeichnis konnte nicht erstellt werden:', - 'A temporary file could not be created. Please verify that the directory "#1" is writeable by the webserver.' => 'Eine temporäre Datei konnte nicht angelegt werden. Bitte stellen Sie sicher, dass das Verzeichnis "#1" vom Webserver beschrieben werden darf.', 'A temporary file could not be created:' => 'Eine temporäre Datei konnte nicht erstellt werden:', 'A unit with this name does already exist.' => 'Eine Einheit mit diesem Namen existiert bereits.', 'A valid taxkey is missing!' => 'Einen gültiger Steuerschlüssel fehlt!', @@ -372,7 +371,6 @@ $self->{texts} = { 'Cancel' => 'Abbrechen', 'Cancel Accounts Payables Transaction' => 'Kreditorenbuchung stornieren', 'Cancel Accounts Receivables Transaction' => 'Debitorenbuchung stornieren', - 'Cannot create Lock!' => 'System kann nicht gesperrt werden!', 'Cannot delete account!' => 'Konto kann nicht gelöscht werden!', 'Cannot delete customer!' => 'Kunde kann nicht gelöscht werden!', 'Cannot delete default account!' => 'Das Standard-Konto kann nicht gelöscht werden!', @@ -454,6 +452,7 @@ $self->{texts} = { 'Close Flash' => 'Schließen', 'Close SEPA exports' => 'SEPA-Export abschließen', 'Close Window' => 'Fenster Schließen', + 'Close window' => 'Fenster schließen', 'Closed' => 'Geschlossen', 'Collective Orders only work for orders from one customer!' => 'Sammelaufträge funktionieren nur für Aufträge von einem Kunden!', 'Column name' => 'Spaltenname', @@ -931,6 +930,7 @@ $self->{texts} = { 'Filter date by' => 'Datum filtern nach', 'Filter for customer variables' => 'Filter für benutzerdefinierte Kundenvariablen', 'Filter for item variables' => 'Filter für benutzerdefinierte Artikelvariablen', + 'Filter parts' => 'Artikel filtern', 'Finish' => 'Abschließen', 'First 20 Lines' => 'Nur erste 20 Datensätze', 'Fix transaction' => 'Buchung korrigieren', @@ -1213,6 +1213,7 @@ $self->{texts} = { 'Loading...' => 'Wird geladen...', 'Local Tax Office Preferences' => 'Angaben zum Finanzamt', 'Lock System' => 'System sperren', + 'Lock file handling failed. Please verify that the directory "#1" is writeable by the webserver.' => 'Die Lockdateibehandlung schlug fehl. Bitte stellen Sie sicher, dass der Webserver das Verzeichnis "#1" beschreiben darf.', 'Lockfile created!' => 'System gesperrt!', 'Lockfile removed!' => 'System entsperrt!', 'Login' => 'Anmelden', @@ -1319,7 +1320,6 @@ $self->{texts} = { 'No Company Address given' => 'Keine Firmenadresse hinterlegt!', 'No Company Name given' => 'Kein Firmenname hinterlegt!', 'No Customer was found matching the search parameters.' => 'Zu dem Suchbegriff wurde kein Endkunde gefunden', - 'No Database Drivers available!' => 'Kein Datenbanktreiber verfügbar!', 'No Dataset selected!' => 'Keine Datenbank ausgewählt!', 'No Vendor was found matching the search parameters.' => 'Zu dem Suchbegriff wurde kein Händler gefunden', 'No action defined.' => 'Keine Aktion definiert.', @@ -2369,6 +2369,7 @@ $self->{texts} = { 'Valid' => 'Gültig', 'Valid from' => 'Gültig ab', 'Valid until' => 'gültig bis', + 'Valid/Obsolete' => 'Gültig/ungültig', 'Value' => 'Wert', 'Variable' => 'Variable', 'Variable Description' => 'Datenfeldbezeichnung', -- 2.20.1