SL::DBConnect: zu verwendende Datenbankinfos via SL::DB->_register_db erhalten
[kivitendo-erp.git] / SL / Auth.pm
index ddd8233..453354d 100644 (file)
@@ -26,6 +26,11 @@ use strict;
 use constant SESSION_KEY_ROOT_AUTH => 'session_auth_status_root';
 use constant SESSION_KEY_USER_AUTH => 'session_auth_status_user';
 
+use Rose::Object::MakeMethods::Generic (
+  scalar => [ qw(client) ],
+);
+
+
 sub new {
   $main::lxdebug->enter_sub();
 
@@ -51,6 +56,23 @@ sub reset {
   $self->{unique_counter}     = 0;
   $self->{column_information} = SL::Auth::ColumnInformation->new(auth => $self);
   $self->{authenticator}->reset;
+
+  $self->client(undef);
+}
+
+sub set_client {
+  my ($self, $id_or_name) = @_;
+
+  $self->client(undef);
+
+  my $column = $id_or_name =~ m/^\d+$/ ? 'id' : 'name';
+  my $dbh    = $self->dbconnect;
+
+  return undef unless $dbh;
+
+  $self->client($dbh->selectrow_hashref(qq|SELECT * FROM auth.clients WHERE ${column} = ?|, undef, $id_or_name));
+
+  return $self->client;
 }
 
 sub get_user_dbh {
@@ -330,7 +352,7 @@ sub create_database {
     my ($cluster_encoding) = $dbh->selectrow_array($query);
 
     if ($cluster_encoding && ($cluster_encoding =~ m/^(?:UTF-?8|UNICODE)$/i) && ($encoding !~ m/^(?:UTF-?8|UNICODE)$/i)) {
-      $error = $main::locale->text('Your PostgreSQL installationen uses UTF-8 as its encoding. Therefore you have to configure Lx-Office to use UTF-8 as well.');
+      $error = $main::locale->text('Your PostgreSQL installationen uses UTF-8 as its encoding. Therefore you have to configure kivitendo to use UTF-8 as well.');
     }
 
     $dbh->disconnect();
@@ -489,8 +511,15 @@ sub read_user {
     @user_data{qw(id login)}    = @{$ref}{qw(id login)};
   }
 
-  # The XUL/XML backed menu has been removed.
-  $user_data{menustyle} = 'v3' if lc($user_data{menustyle} || '') eq 'xml';
+  # The XUL/XML & 'CSS new' backed menus have been removed.
+  my %menustyle_map = ( xml => 'new', v4 => 'v3' );
+  $user_data{menustyle} = $menustyle_map{lc($user_data{menustyle} || '')} || $user_data{menustyle};
+
+  # The 'Win2000.css' stylesheet has been removed.
+  $user_data{stylesheet} = 'kivitendo.css' if ($user_data{stylesheet} || '') =~ m/win2000/i;
+
+  # Set default language if selected language does not exist (anymore).
+  $user_data{countrycode} = $::lx_office_conf{system}->{language} unless $user_data{countrycode} && -d "locale/$user_data{countrycode}";
 
   $sth->finish();
 
@@ -559,7 +588,7 @@ sub restore_session {
 
   if (!$session_id) {
     $main::lxdebug->leave_sub();
-    return SESSION_NONE;
+    return $self->session_restore_result(SESSION_NONE());
   }
 
   my ($dbh, $query, $sth, $cookie, $ref, $form);
@@ -569,7 +598,7 @@ sub restore_session {
   # Don't fail if the auth DB doesn't yet.
   if (!( $dbh = $self->dbconnect(1) )) {
     $::lxdebug->leave_sub;
-    return SESSION_NONE;
+    return $self->session_restore_result(SESSION_NONE());
   }
 
   # Don't fail if the "auth" schema doesn't exist yet, e.g. if the
@@ -579,16 +608,26 @@ sub restore_session {
   if (!($sth = $dbh->prepare($query)) || !$sth->execute($session_id)) {
     $sth->finish if $sth;
     $::lxdebug->leave_sub;
-    return SESSION_NONE;
+    return $self->session_restore_result(SESSION_NONE());
   }
 
   $cookie = $sth->fetchrow_hashref;
   $sth->finish;
 
-  if (!$cookie || $cookie->{is_expired} || ($cookie->{ip_address} ne $ENV{REMOTE_ADDR})) {
+  # The session ID provided is valid in the following cases:
+  #  1. session ID exists in the database
+  #  2. hasn't expired yet
+  #  3. if form field '{AUTH}api_token' is given: form field must equal database column 'auth.session.api_token' for the session ID
+  #  4. if form field '{AUTH}api_token' is NOT given then: the requestee's IP address must match the stored IP address
+  $self->{api_token}   = $cookie->{api_token} if $cookie;
+  my $api_token_cookie = $self->get_api_token_cookie;
+  my $cookie_is_bad    = !$cookie || $cookie->{is_expired};
+  $cookie_is_bad     ||= $api_token_cookie && ($api_token_cookie ne $cookie->{api_token}) if  $api_token_cookie;
+  $cookie_is_bad     ||= $cookie->{ip_address} ne $ENV{REMOTE_ADDR}                       if !$api_token_cookie;
+  if ($cookie_is_bad) {
     $self->destroy_session();
     $main::lxdebug->leave_sub();
-    return $cookie ? SESSION_EXPIRED : SESSION_NONE;
+    return $self->session_restore_result($cookie ? SESSION_EXPIRED() : SESSION_NONE());
   }
 
   if ($self->{column_information}->has('auto_restore')) {
@@ -599,7 +638,15 @@ sub restore_session {
 
   $main::lxdebug->leave_sub();
 
-  return SESSION_OK;
+  return $self->session_restore_result(SESSION_OK());
+}
+
+sub session_restore_result {
+  my $self = shift;
+  if (@_) {
+    $self->{session_restore_result} = $_[0];
+  }
+  return $self->{session_restore_result};
 }
 
 sub _load_without_auto_restore_column {
@@ -696,6 +743,17 @@ sub destroy_session {
   $main::lxdebug->leave_sub();
 }
 
+sub active_session_ids {
+  my $self  = shift;
+  my $dbh   = $self->dbconnect;
+
+  my $query = qq|SELECT id FROM auth.session|;
+
+  my @ids   = selectall_array_query($::form, $dbh, $query);
+
+  return @ids;
+}
+
 sub expire_sessions {
   $main::lxdebug->enter_sub();
 
@@ -784,6 +842,11 @@ sub save_session {
     do_query($::form, $dbh, qq|INSERT INTO auth.session (id, ip_address, mtime) VALUES (?, ?, now())|, $session_id, $ENV{REMOTE_ADDR});
   }
 
+  if ($self->{column_information}->has('api_token', 'session')) {
+    my ($stored_api_token) = $dbh->selectrow_array(qq|SELECT api_token FROM auth.session WHERE id = ?|, undef, $session_id);
+    do_query($::form, $dbh, qq|UPDATE auth.session SET api_token = ? WHERE id = ?|, $self->_create_session_id, $session_id) unless $stored_api_token;
+  }
+
   my @values_to_save = grep    { $_->{fetched} }
                        values %{ $self->{SESSION} };
   if (@values_to_save) {
@@ -920,15 +983,25 @@ sub set_cookie_environment_variable {
 }
 
 sub get_session_cookie_name {
-  my $self = shift;
+  my ($self, %params) = @_;
 
-  return $self->{cookie_name} || 'lx_office_erp_session_id';
+  $params{type}     ||= 'id';
+  my $name            = $self->{cookie_name} || 'lx_office_erp_session_id';
+  $name              .= '_api_token' if $params{type} eq 'api_token';
+
+  return $name;
 }
 
 sub get_session_id {
   return $session_id;
 }
 
+sub get_api_token_cookie {
+  my ($self) = @_;
+
+  $::request->{cgi}->cookie($self->get_session_cookie_name(type => 'api_token'));
+}
+
 sub session_tables_present {
   $main::lxdebug->enter_sub();
 
@@ -1015,8 +1088,10 @@ sub all_rights_full {
     ["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')")],
+    ["config",                         $locale->text("Change kivitendo installation settings (all menu entries beneath 'System')")],
     ["admin",                          $locale->text("Administration (Used to access instance administration from user logins)")],
+    ["productivity",                   $locale->text("Productivity")],
+    ["display_admin_link",             $locale->text("Show administration link")],
     );
 
   return @all_rights;