Merge branch 'csv-import-in-perl'
[kivitendo-erp.git] / SL / Auth.pm
index 0951883..784b185 100644 (file)
@@ -12,6 +12,7 @@ use SL::Auth::Constants qw(:all);
 use SL::Auth::DB;
 use SL::Auth::LDAP;
 
 use SL::Auth::DB;
 use SL::Auth::LDAP;
 
+use SL::SessionFile;
 use SL::User;
 use SL::DBConnect;
 use SL::DBUpgrade2;
 use SL::User;
 use SL::DBConnect;
 use SL::DBUpgrade2;
@@ -36,8 +37,19 @@ sub new {
   return $self;
 }
 
   return $self;
 }
 
+sub reset {
+  my ($self, %params) = @_;
+
+  $self->{SESSION}          = { };
+  $self->{FULL_RIGHTS}      = { };
+  $self->{RIGHTS}           = { };
+  $self->{unique_counter}   = 0;
+}
+
 sub get_user_dbh {
 sub get_user_dbh {
-  my ($self, $login) = @_;
+  my ($self, $login, %params) = @_;
+  my $may_fail = delete $params{may_fail};
+
   my %user = $self->read_user($login);
   my $dbh  = SL::DBConnect->connect(
     $user{dbconnect},
   my %user = $self->read_user($login);
   my $dbh  = SL::DBConnect->connect(
     $user{dbconnect},
@@ -47,9 +59,13 @@ sub get_user_dbh {
       pg_enable_utf8 => $::locale->is_utf8,
       AutoCommit     => 0
     }
       pg_enable_utf8 => $::locale->is_utf8,
       AutoCommit     => 0
     }
-  ) or $::form->dberror;
+  );
+
+  if (!$may_fail && !$dbh) {
+    $::form->error($::locale->text('The connection to the authentication database failed:') . "\n" . $DBI::errstr);
+  }
 
 
-  if ($user{dboptions}) {
+  if ($user{dboptions} && $dbh) {
     $dbh->do($user{dboptions}) or $::form->dberror($user{dboptions});
   }
 
     $dbh->do($user{dboptions}) or $::form->dberror($user{dboptions});
   }
 
@@ -247,7 +263,7 @@ sub create_database {
   my $encoding   = $Common::charset_to_db_encoding{$charset};
   $encoding    ||= 'UNICODE';
 
   my $encoding   = $Common::charset_to_db_encoding{$charset};
   $encoding    ||= 'UNICODE';
 
-  my $dbh        = SL::DBConnect->connect($dsn, $params{superuser}, $params{superuser_password}, { pg_enable_utf8 => $charset =~ m/^utf-?8$/i });
+  my $dbh        = SL::DBConnect->connect($dsn, $params{superuser}, $params{superuser_password}, { pg_enable_utf8 => scalar($charset =~ m/^utf-?8$/i) });
 
   if (!$dbh) {
     $main::form->error($main::locale->text('The connection to the template database failed:') . "\n" . $DBI::errstr);
 
   if (!$dbh) {
     $main::form->error($main::locale->text('The connection to the template database failed:') . "\n" . $DBI::errstr);
@@ -421,29 +437,30 @@ sub get_user_id {
 }
 
 sub delete_user {
 }
 
 sub delete_user {
-  $main::lxdebug->enter_sub();
+  $::lxdebug->enter_sub;
 
   my $self  = shift;
   my $login = shift;
 
 
   my $self  = shift;
   my $login = shift;
 
-  my $form  = $main::form;
-
-  my $dbh   = $self->dbconnect();
+  my $u_dbh = $self->get_user_dbh($login, may_fail => 1);
+  my $dbh   = $self->dbconnect;
 
   $dbh->begin_work;
 
   my $query = qq|SELECT id FROM auth."user" WHERE login = ?|;
 
 
   $dbh->begin_work;
 
   my $query = qq|SELECT id FROM auth."user" WHERE login = ?|;
 
-  my ($id)  = selectrow_query($form, $dbh, $query, $login);
+  my ($id)  = selectrow_query($::form, $dbh, $query, $login);
 
 
-  $dbh->rollback and return $main::lxdebug->leave_sub() if (!$id);
+  $dbh->rollback and return $::lxdebug->leave_sub if (!$id);
 
 
-  do_query($form, $dbh, qq|DELETE FROM auth.user_group WHERE user_id = ?|, $id);
-  do_query($form, $dbh, qq|DELETE FROM auth.user_config WHERE user_id = ?|, $id);
+  do_query($::form, $dbh, qq|DELETE FROM auth.user_group WHERE user_id = ?|, $id);
+  do_query($::form, $dbh, qq|DELETE FROM auth.user_config WHERE user_id = ?|, $id);
+  do_query($::form, $u_dbh, qq|UPDATE employee SET deleted = 't' WHERE login = ?|, $login) if $u_dbh;
 
 
-  $dbh->commit();
+  $dbh->commit;
+  $u_dbh->commit if $u_dbh;
 
 
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 # --------------------------------------
 }
 
 # --------------------------------------
@@ -539,6 +556,8 @@ sub destroy_session {
 
     $dbh->commit();
 
 
     $dbh->commit();
 
+    SL::SessionFile->destroy_session($session_id);
+
     $session_id      = undef;
     $self->{SESSION} = { };
   }
     $session_id      = undef;
     $self->{SESSION} = { };
   }
@@ -551,26 +570,31 @@ sub expire_sessions {
 
   my $self  = shift;
 
 
   my $self  = shift;
 
+  $main::lxdebug->leave_sub and return if !$self->session_tables_present;
+
   my $dbh   = $self->dbconnect();
 
   my $dbh   = $self->dbconnect();
 
-  $dbh->begin_work;
+  my $query = qq|SELECT id
+                 FROM auth.session
+                 WHERE (mtime < (now() - '$self->{session_timeout}m'::interval))|;
 
 
-  my $query =
-    qq|DELETE FROM auth.session_content
-       WHERE session_id IN
-         (SELECT id
-          FROM auth.session
-          WHERE (mtime < (now() - '$self->{session_timeout}m'::interval)))|;
+  my @ids   = selectall_array_query($::form, $dbh, $query);
 
 
-  do_query($main::form, $dbh, $query);
+  if (@ids) {
+    $dbh->begin_work;
 
 
-  $query =
-    qq|DELETE FROM auth.session
-       WHERE (mtime < (now() - '$self->{session_timeout}m'::interval))|;
+    SL::SessionFile->destroy_session($_) for @ids;
 
 
-  do_query($main::form, $dbh, $query);
+    $query = qq|DELETE FROM auth.session_content
+                WHERE session_id IN (| . join(', ', ('?') x scalar(@ids)) . qq|)|;
+    do_query($main::form, $dbh, $query, @ids);
 
 
-  $dbh->commit();
+    $query = qq|DELETE FROM auth.session
+                WHERE id IN (| . join(', ', ('?') x scalar(@ids)) . qq|)|;
+    do_query($main::form, $dbh, $query, @ids);
+
+    $dbh->commit();
+  }
 
   $main::lxdebug->leave_sub();
 }
 
   $main::lxdebug->leave_sub();
 }
@@ -589,52 +613,33 @@ sub _create_session_id {
 }
 
 sub create_or_refresh_session {
 }
 
 sub create_or_refresh_session {
-  $main::lxdebug->enter_sub();
-
-  my $self = shift;
-
-  $session_id ||= $self->_create_session_id();
-
-  my ($form, $dbh, $query, $sth, $id);
-
-  $form  = $main::form;
-  $dbh   = $self->dbconnect();
-
-  $dbh->begin_work;
-  do_query($::form, $dbh, qq|LOCK auth.session_content|);
-
-  $query = qq|SELECT id FROM auth.session WHERE id = ?|;
-
-  ($id)  = selectrow_query($form, $dbh, $query, $session_id);
-
-  if ($id) {
-    do_query($form, $dbh, qq|UPDATE auth.session SET mtime = now() WHERE id = ?|, $session_id);
-
-  } else {
-    do_query($form, $dbh, qq|INSERT INTO auth.session (id, ip_address, mtime) VALUES (?, ?, now())|, $session_id, $ENV{REMOTE_ADDR});
-
-  }
-
-  $self->save_session($dbh);
-
-  $dbh->commit();
-
-  $main::lxdebug->leave_sub();
+  $session_id ||= shift->_create_session_id;
 }
 
 sub save_session {
 }
 
 sub save_session {
+  $::lxdebug->enter_sub;
   my $self         = shift;
   my $provided_dbh = shift;
 
   my $dbh          = $provided_dbh || $self->dbconnect(1);
 
   my $self         = shift;
   my $provided_dbh = shift;
 
   my $dbh          = $provided_dbh || $self->dbconnect(1);
 
-  return unless $dbh;
+  $::lxdebug->leave_sub && return unless $dbh && $session_id;
 
   $dbh->begin_work unless $provided_dbh;
 
   do_query($::form, $dbh, qq|LOCK auth.session_content|);
   do_query($::form, $dbh, qq|DELETE FROM auth.session_content WHERE session_id = ?|, $session_id);
 
 
   $dbh->begin_work unless $provided_dbh;
 
   do_query($::form, $dbh, qq|LOCK auth.session_content|);
   do_query($::form, $dbh, qq|DELETE FROM auth.session_content WHERE session_id = ?|, $session_id);
 
+  my $query = qq|SELECT id FROM auth.session WHERE id = ?|;
+
+  my ($id)  = selectrow_query($::form, $dbh, $query, $session_id);
+
+  if ($id) {
+    do_query($::form, $dbh, qq|UPDATE auth.session SET mtime = now() WHERE id = ?|, $session_id);
+  } else {
+    do_query($::form, $dbh, qq|INSERT INTO auth.session (id, ip_address, mtime) VALUES (?, ?, now())|, $session_id, $ENV{REMOTE_ADDR});
+  }
+
   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);
   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);
@@ -647,6 +652,7 @@ sub save_session {
   }
 
   $dbh->commit() unless $provided_dbh;
   }
 
   $dbh->commit() unless $provided_dbh;
+  $::lxdebug->leave_sub;
 }
 
 sub set_session_value {
 }
 
 sub set_session_value {
@@ -703,7 +709,6 @@ sub create_unique_sesion_value {
   $self->{unique_counter}++;
 
   $value  = { expiration => $params{expiration} ? ($now[0] + $params{expiration}) * 1000000 + $now[1] : undef,
   $self->{unique_counter}++;
 
   $value  = { expiration => $params{expiration} ? ($now[0] + $params{expiration}) * 1000000 + $now[1] : undef,
-              no_auto    => !$params{auto_restore},
               data       => $value,
             };
 
               data       => $value,
             };
 
@@ -782,6 +787,14 @@ sub session_tables_present {
   $main::lxdebug->enter_sub();
 
   my $self = shift;
   $main::lxdebug->enter_sub();
 
   my $self = shift;
+
+  # Only re-check for the presence of auth tables if either the check
+  # hasn't been done before of if they weren't present.
+  if ($self->{session_tables_present}) {
+    $main::lxdebug->leave_sub();
+    return $self->{session_tables_present};
+  }
+
   my $dbh  = $self->dbconnect(1);
 
   if (!$dbh) {
   my $dbh  = $self->dbconnect(1);
 
   if (!$dbh) {
@@ -797,9 +810,11 @@ sub session_tables_present {
 
   my ($count) = selectrow_query($main::form, $dbh, $query);
 
 
   my ($count) = selectrow_query($main::form, $dbh, $query);
 
+  $self->{session_tables_present} = 2 == $count;
+
   $main::lxdebug->leave_sub();
 
   $main::lxdebug->leave_sub();
 
-  return 2 == $count;
+  return $self->{session_tables_present};
 }
 
 # --------------------------------------
 }
 
 # --------------------------------------
@@ -971,7 +986,7 @@ sub delete_group {
   my $self = shift;
   my $id   = shift;
 
   my $self = shift;
   my $id   = shift;
 
-  my $form = $main::from;
+  my $form = $main::form;
 
   my $dbh  = $self->dbconnect();
   $dbh->begin_work;
 
   my $dbh  = $self->dbconnect();
   $dbh->begin_work;
@@ -1095,41 +1110,32 @@ sub check_right {
 }
 
 sub assert {
 }
 
 sub assert {
-  $main::lxdebug->enter_sub(2);
-
-  my $self       = shift;
-  my $right      = shift;
-  my $dont_abort = shift;
-
-  my $form       = $main::form;
+  $::lxdebug->enter_sub(2);
+  my ($self, $right, $dont_abort) = @_;
 
 
-  if ($self->check_right($form->{login}, $right)) {
-    $main::lxdebug->leave_sub(2);
+  if ($self->check_right($::myconfig{login}, $right)) {
+    $::lxdebug->leave_sub(2);
     return 1;
   }
 
   if (!$dont_abort) {
     return 1;
   }
 
   if (!$dont_abort) {
-    delete $form->{title};
-    $form->show_generic_error($main::locale->text("You do not have the permissions to access this function."));
+    delete $::form->{title};
+    $::form->show_generic_error($::locale->text("You do not have the permissions to access this function."));
   }
 
   }
 
-  $main::lxdebug->leave_sub(2);
+  $::lxdebug->leave_sub(2);
 
   return 0;
 }
 
 sub load_rights_for_user {
 
   return 0;
 }
 
 sub load_rights_for_user {
-  $main::lxdebug->enter_sub();
-
-  my $self  = shift;
-  my $login = shift;
-
-  my $form  = $main::form;
-  my $dbh   = $self->dbconnect();
+  $::lxdebug->enter_sub;
 
 
+  my ($self, $login) = @_;
+  my $dbh   = $self->dbconnect;
   my ($query, $sth, $row, $rights);
 
   my ($query, $sth, $row, $rights);
 
-  $rights = {};
+  $rights = { map { $_ => 0 } all_rights() };
 
   $query =
     qq|SELECT gr."right", gr.granted
 
   $query =
     qq|SELECT gr."right", gr.granted
@@ -1140,16 +1146,14 @@ sub load_rights_for_user {
           LEFT JOIN auth."user" u ON (ug.user_id = u.id)
           WHERE u.login = ?)|;
 
           LEFT JOIN auth."user" u ON (ug.user_id = u.id)
           WHERE u.login = ?)|;
 
-  $sth = prepare_execute_query($form, $dbh, $query, $login);
+  $sth = prepare_execute_query($::form, $dbh, $query, $login);
 
   while ($row = $sth->fetchrow_hashref()) {
     $rights->{$row->{right}} |= $row->{granted};
   }
   $sth->finish();
 
 
   while ($row = $sth->fetchrow_hashref()) {
     $rights->{$row->{right}} |= $row->{granted};
   }
   $sth->finish();
 
-  map({ $rights->{$_} = 0 unless (defined $rights->{$_}); } SL::Auth::all_rights());
-
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 
   return $rights;
 }
 
   return $rights;
 }
@@ -1191,11 +1195,6 @@ If C<$params{expiration}> is set then it is interpreted as a number of
 seconds after which the value is removed from the session. It will
 never expire if that parameter is falsish.
 
 seconds after which the value is removed from the session. It will
 never expire if that parameter is falsish.
 
-If C<$params{auto_restore}> is trueish then the value will be copied
-into C<$::form> upon the next request automatically. It defaults to
-C<false> and has therefore different behaviour than
-L</set_session_value>.
-
 Returns the key created in the session.
 
 =item C<expire_session_keys>
 Returns the key created in the session.
 
 =item C<expire_session_keys>