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) ],
);
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');
}
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');
}
#
#
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 }
# 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();
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();
}
form => $::form,
auth => 1
);
- User->dbupdate2($form, $scripts->parse_dbupdate_controls);
+ User->dbupdate2(form => $form,
+ updater => $scripts->parse_dbupdate_controls,
+ database => $dbname);
=head1 OVERVIEW
Perl scripts are executed via L<eval>. If L<eval> 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:
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!'));
}
--- /dev/null
+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<debug.keep_installation_unlocked>. If it is trueish then all of
+these commands will always keep the installation unlocked: L</lock>
+and L</unlock> won't do anything and L</is_locked> always returns 0.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<is_locked>
+
+Returns 1 or 0 depending on whether or not the installation is currently locked.
+
+=item C<lock>
+
+Creates the lock file. Throws an exception if writing to the lock file
+location fails.
+
+=item C<lock_file_name>
+
+Returns the file name for the global lock file.
+
+=item C<unlock>
+
+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 E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
use SL::DBUtils;
use SL::Iconv;
use SL::Inifile;
+use SL::System::InstallationLock;
use strict;
}
# 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';
$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");
'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!',
'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!',
'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',
'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',
'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',
'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.',
'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',