package SL::Auth;
-use constant OK => 0;
-use constant ERR_PASSWORD => 1;
-use constant ERR_BACKEND => 100;
-
-use constant SESSION_OK => 0;
-use constant SESSION_NONE => 1;
-use constant SESSION_EXPIRED => 2;
+use DBI;
use Digest::MD5 qw(md5_hex);
use IO::File;
use Time::HiRes qw(gettimeofday);
use List::MoreUtils qw(uniq);
+use YAML;
+use SL::Auth::Constants qw(:all);
use SL::Auth::DB;
use SL::Auth::LDAP;
use SL::User;
+use SL::DBUpgrade2;
use SL::DBUtils;
+use strict;
+
sub new {
$main::lxdebug->enter_sub();
return $self;
}
+sub get_user_dbh {
+ my ($self, $login) = @_;
+ my %user = $self->read_user($login);
+ my $dbh = DBI->connect(
+ $user{dbconnect},
+ $user{dbuser},
+ $user{dbpasswd},
+ {
+ pg_enable_utf8 => $::locale->is_utf8,
+ AutoCommit => 0
+ }
+ ) or $::form->dberror;
+
+ if ($user{dboptions}) {
+ $dbh->do($user{dboptions}) or $::form->dberror($user{dboptions});
+ }
+
+ return $dbh;
+}
+
sub DESTROY {
my $self = shift;
$self->{dbh}->disconnect() if ($self->{dbh});
}
+# form isn't loaded yet, so auth needs it's own error.
+sub mini_error {
+ $::lxdebug->show_backtrace();
+
+ my ($self, @msg) = @_;
+ if ($ENV{HTTP_USER_AGENT}) {
+ print Form->create_http_response(content_type => 'text/html');
+ print "<pre>", join ('<br>', @msg), "</pre>";
+ } else {
+ print STDERR "Error: @msg\n";
+ }
+ ::end_of_request();
+}
+
sub _read_auth_config {
$main::lxdebug->enter_sub();
my $self = shift;
- my $form = $main::form;
- my $locale = $main::locale;
-
my $code;
my $in = IO::File->new('config/authentication.pl', 'r');
if (!$in) {
- $form->error($locale->text('The config file "config/authentication.pl" was not found.'));
+ my $locale = Locale->new('en');
+ $self->mini_error($locale->text('The config file "config/authentication.pl" was not found.'));
}
while (<$in>) {
eval $code;
if ($@) {
- $form->error($locale->text('The config file "config/authentication.pl" contained invalid Perl code:') . "\n" . $@);
+ my $locale = Locale->new('en');
+ $self->mini_error($locale->text('The config file "config/authentication.pl" contained invalid Perl code:'), $@);
}
if ($self->{module} eq 'DB') {
}
if (!$self->{authenticator}) {
- $form->error($locale->text('No or an unknown authenticantion module specified in "config/authentication.pl".'));
+ my $locale = Locale->new('en');
+ $self->mini_error($locale->text('No or an unknown authenticantion module specified in "config/authentication.pl".'));
}
my $cfg = $self->{DB_config};
if (!$cfg) {
- $form->error($locale->text('config/authentication.pl: Key "DB_config" is missing.'));
+ my $locale = Locale->new('en');
+ $self->mini_error($locale->text('config/authentication.pl: Key "DB_config" is missing.'));
}
if (!$cfg->{host} || !$cfg->{db} || !$cfg->{user}) {
- $form->error($locale->text('config/authentication.pl: Missing parameters in "DB_config". Required parameters are "host", "db" and "user".'));
+ my $locale = Locale->new('en');
+ $self->mini_error($locale->text('config/authentication.pl: Missing parameters in "DB_config". Required parameters are "host", "db" and "user".'));
}
$self->{authenticator}->verify_config();
$main::lxdebug->leave_sub();
- return $password eq $admin_password ? OK : ERR_PASSWORD;
+ return OK if $password eq $admin_password;
+ sleep 5;
+ return ERR_PASSWORD;
}
sub authenticate {
$main::lxdebug->leave_sub();
- return $self->{authenticator}->authenticate(@_);
+ my $result = $self->{authenticator}->authenticate(@_);
+ return OK if $result eq OK;
+ sleep 5;
+ return $result;
}
sub dbconnect {
$dsn .= ';port=' . $cfg->{port};
}
- $main::lxdebug->message(LXDebug::DEBUG1, "Auth::dbconnect DSN: $dsn");
+ $main::lxdebug->message(LXDebug->DEBUG1, "Auth::dbconnect DSN: $dsn");
- $self->{dbh} = DBI->connect($dsn, $cfg->{user}, $cfg->{password}, { 'AutoCommit' => 0 });
+ $self->{dbh} = DBI->connect($dsn, $cfg->{user}, $cfg->{password}, { pg_enable_utf8 => $::locale->is_utf8, AutoCommit => 0 });
if (!$may_fail && !$self->{dbh}) {
$main::form->error($main::locale->text('The connection to the authentication database failed:') . "\n" . $DBI::errstr);
}
- $main::lxdebug->leave_sub();
+ $main::lxdebug->leave_sub(2);
return $self->{dbh};
}
$dsn .= ';port=' . $cfg->{port};
}
- $main::lxdebug->message(LXDebug::DEBUG1, "Auth::create_database DSN: $dsn");
-
- my $dbh = DBI->connect($dsn, $params{superuser}, $params{superuser_password});
-
- if (!$dbh) {
- $main::form->error($main::locale->text('The connection to the template database failed:') . "\n" . $DBI::errstr);
- }
+ $main::lxdebug->message(LXDebug->DEBUG1(), "Auth::create_database DSN: $dsn");
my $charset = $main::dbcharset;
$charset ||= Common::DEFAULT_CHARSET;
my $encoding = $Common::charset_to_db_encoding{$charset};
$encoding ||= 'UNICODE';
+ my $dbh = DBI->connect($dsn, $params{superuser}, $params{superuser_password}, { pg_enable_utf8 => $charset =~ m/^utf-?8$/i });
+
+ if (!$dbh) {
+ $main::form->error($main::locale->text('The connection to the template database failed:') . "\n" . $DBI::errstr);
+ }
+
my $query = qq|CREATE DATABASE "$cfg->{db}" OWNER "$cfg->{user}" TEMPLATE "$params{template}" ENCODING '$encoding'|;
- $main::lxdebug->message(LXDebug::DEBUG1, "Auth::create_database query: $query");
+ $main::lxdebug->message(LXDebug->DEBUG1(), "Auth::create_database query: $query");
$dbh->do($query);
$charset ||= Common::DEFAULT_CHARSET;
$dbh->rollback();
- User->process_query($main::form, $dbh, 'sql/auth_db.sql', undef, $charset);
+ SL::DBUpgrade2->new(form => $::form)->process_query($dbh, 'sql/auth_db.sql', undef, $charset);
$main::lxdebug->leave_sub();
}
if (!$cookie || $cookie->{is_expired} || ($cookie->{ip_address} ne $ENV{REMOTE_ADDR})) {
$self->destroy_session();
$main::lxdebug->leave_sub();
- return SESSION_EXPIRED;
+ return $cookie ? SESSION_EXPIRED : SESSION_NONE;
}
$query = qq|SELECT sess_key, sess_value FROM auth.session_content WHERE session_id = ?|;
while (my $ref = $sth->fetchrow_hashref()) {
$self->{SESSION}->{$ref->{sess_key}} = $ref->{sess_value};
- $form->{$ref->{sess_key}} = $ref->{sess_value} if (!defined $form->{$ref->{sess_key}});
+ $form->{$ref->{sess_key}} = $self->_load_value($ref->{sess_value}) if (!defined $form->{$ref->{sess_key}});
}
$sth->finish();
return SESSION_OK;
}
+sub _load_value {
+ return $_[1] if $_[1] !~ m/^---/;
+
+ my $value;
+ eval {
+ $value = YAML::Load($_[1]);
+ 1;
+ } or return $_[1];
+
+ return $value;
+}
+
sub destroy_session {
$main::lxdebug->enter_sub();
if ($id) {
do_query($form, $dbh, qq|UPDATE auth.session SET mtime = now() WHERE id = ?|, $session_id);
- do_query($form, $dbh, qq|DELETE FROM auth.session_content WHERE session_id = ?|, $session_id);
} else {
do_query($form, $dbh, qq|INSERT INTO auth.session (id, ip_address, mtime) VALUES (?, ?, now())|, $session_id, $ENV{REMOTE_ADDR});
}
- $query = qq|INSERT INTO auth.session_content (session_id, sess_key, sess_value) VALUES (?, ?, ?)|;
- $sth = prepare_query($form, $dbh, $query);
+ $self->save_session($dbh);
- foreach my $key (sort keys %{ $self->{SESSION} }) {
- do_statement($form, $sth, $query, $session_id, $key, $self->{SESSION}->{$key});
- }
-
- $sth->finish();
$dbh->commit();
$main::lxdebug->leave_sub();
}
+sub save_session {
+ my $self = shift;
+ my $provided_dbh = shift;
+
+ my $dbh = $provided_dbh || $self->dbconnect();
+
+ do_query($::form, $dbh, qq|DELETE FROM auth.session_content WHERE session_id = ?|, $session_id);
+
+ if (%{ $self->{SESSION} }) {
+ my $query = qq|INSERT INTO auth.session_content (session_id, sess_key, sess_value) VALUES (?, ?, ?)|;
+ my $sth = prepare_query($::form, $dbh, $query);
+
+ foreach my $key (sort keys %{ $self->{SESSION} }) {
+ do_statement($::form, $sth, $query, $session_id, $key, $self->{SESSION}->{$key});
+ }
+
+ $sth->finish();
+ }
+
+ $dbh->commit() unless $provided_dbh;
+}
+
sub set_session_value {
$main::lxdebug->enter_sub();
- my $self = shift;
+ my $self = shift;
+ my %params = @_;
$self->{SESSION} ||= { };
- while (2 <= scalar @_) {
- my $key = shift;
- my $value = shift;
-
- $self->{SESSION}->{$key} = $value;
+ while (my ($key, $value) = each %params) {
+ $self->{SESSION}->{ $key } = YAML::Dump($value);
}
$main::lxdebug->leave_sub();
+
+ return $self;
+}
+
+sub delete_session_value {
+ $main::lxdebug->enter_sub();
+
+ my $self = shift;
+
+ $self->{SESSION} ||= { };
+ delete @{ $self->{SESSION} }{ @_ };
+
+ $main::lxdebug->leave_sub();
+
+ return $self;
+}
+
+sub get_session_value {
+ $main::lxdebug->enter_sub();
+
+ my $self = shift;
+ my $value = $self->{SESSION} ? $self->_load_value($self->{SESSION}->{ $_[0] }) : undef;
+
+ $main::lxdebug->leave_sub();
+
+ return $value;
}
sub set_cookie_environment_variable {
["sales_delivery_order_edit", $locale->text("Create and edit sales delivery orders")],
["invoice_edit", $locale->text("Create and edit invoices and credit notes")],
["dunning_edit", $locale->text("Create and edit dunnings")],
+ ["sales_all_edit", $locale->text("View/edit all employees sales documents")],
["--ap", $locale->text("AP")],
["request_quotation_edit", $locale->text("Create and edit RFQs")],
["purchase_order_edit", $locale->text("Create and edit purchase orders")],
["--reports", $locale->text('Reports')],
["report", $locale->text('All reports')],
["advance_turnover_tax_return", $locale->text('Advance turnover tax return')],
+ ["--batch_printing", $locale->text("Batch Printing")],
+ ["batch_printing", $locale->text("Batch Printing")],
["--others", $locale->text("Others")],
["email_bcc", $locale->text("May set the BCC field when sending emails")],
["config", $locale->text("Change Lx-Office installation settings (all menu entries beneath 'System')")],
}
}
- $main::lxdebug->enter_sub(2);
+ $main::lxdebug->leave_sub(2);
return $value;
}
pop @stack;
if (!@stack) {
- $main::lxdebug->enter_sub(2);
+ $main::lxdebug->leave_sub(2);
return 0;
}
my $result = ($access || (1 < scalar @stack)) ? 0 : evaluate_rights_ary($stack[0]);
- $main::lxdebug->enter_sub(2);
+ $main::lxdebug->leave_sub(2);
return $result;
}