X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FAuth.pm;h=82be3b8d80cc2601fbfa580b60563400ec78fa8f;hb=b058e195e82aa1f6b7614b8f83be6122ec3d3dca;hp=2323a28412243e8332713e1fdf1b0014566a2575;hpb=4247547d2a925ddad7006cae89e5f9f1fda7d469;p=kivitendo-erp.git diff --git a/SL/Auth.pm b/SL/Auth.pm index 2323a2841..82be3b8d8 100644 --- a/SL/Auth.pm +++ b/SL/Auth.pm @@ -20,7 +20,7 @@ use SL::SessionFile; use SL::User; use SL::DBConnect; use SL::DBUpgrade2; -use SL::DBUtils; +use SL::DBUtils qw(do_query do_statement prepare_execute_query prepare_query selectall_array_query selectrow_query); use strict; @@ -37,12 +37,12 @@ sub new { my $self = bless {}, $type; $self->_read_auth_config(%params); - $self->reset; + $self->init; return $self; } -sub reset { +sub init { my ($self, %params) = @_; $self->{SESSION} = { }; @@ -50,6 +50,28 @@ sub reset { $self->{RIGHTS} = { }; $self->{unique_counter} = 0; $self->{column_information} = SL::Auth::ColumnInformation->new(auth => $self); +} + +sub reset { + my ($self, %params) = @_; + + $self->{SESSION} = { }; + $self->{FULL_RIGHTS} = { }; + $self->{RIGHTS} = { }; + $self->{unique_counter} = 0; + + if ($self->is_db_connected) { + # reset is called during request shutdown already. In case of a + # completely new auth DB this would fail and generate an error + # message even if the user is currently trying to create said auth + # DB. Therefore only fetch the column information if a connection + # has been established. + $self->{column_information} = SL::Auth::ColumnInformation->new(auth => $self); + $self->{column_information}->_fetch; + } else { + delete $self->{column_information}; + } + $self->{authenticator}->reset; $self->client(undef); @@ -89,7 +111,7 @@ sub mini_error { } else { print STDERR "Error: @msg\n"; } - ::end_of_request(); + $::dispatcher->end_request; } sub _read_auth_config { @@ -168,8 +190,8 @@ sub authenticate_root { return ERR_PASSWORD; } - $password = SL::Auth::Password->hash(login => 'root', password => $password); my $admin_password = SL::Auth::Password->hash_if_unhashed(login => 'root', password => $self->{admin_password}->()); + $password = SL::Auth::Password->hash(login => 'root', password => $password, stored_password => $admin_password); my $result = $password eq $admin_password ? OK : ERR_PASSWORD; $self->set_session_value(SESSION_KEY_ROOT_AUTH() => $result); @@ -236,6 +258,7 @@ sub dbconnect { $self->{dbh} = SL::DBConnect->connect($dsn, $cfg->{user}, $cfg->{password}, { pg_enable_utf8 => 1, AutoCommit => 1 }); if (!$may_fail && !$self->{dbh}) { + delete $self->{dbh}; $main::form->error($main::locale->text('The connection to the authentication database failed:') . "\n" . $DBI::errstr); } @@ -251,6 +274,11 @@ sub dbdisconnect { } } +sub is_db_connected { + my ($self) = @_; + return !!$self->{dbh}; +} + sub check_tables { my ($self, $dbh) = @_; @@ -516,7 +544,7 @@ sub restore_session { $form = $main::form; - # Don't fail if the auth DB doesn't yet. + # Don't fail if the auth DB doesn't exist yet. if (!( $dbh = $self->dbconnect(1) )) { return $self->session_restore_result(SESSION_NONE()); } @@ -592,47 +620,36 @@ SQL sub _load_with_auto_restore_column { my ($self, $dbh, $session_id) = @_; - my $auto_restore_keys = join ', ', map { "'${_}'" } qw(login password rpw); + my %auto_restore_keys = map { $_ => 1 } qw(login password rpw client_id), SESSION_KEY_ROOT_AUTH, SESSION_KEY_USER_AUTH; my $query = <fetchrow_hashref) { - my $value = SL::Auth::SessionValue->new(auth => $self, - key => $ref->{sess_key}, - value => $ref->{sess_value}, - auto_restore => $ref->{auto_restore}, - raw => 1); - $self->{SESSION}->{ $ref->{sess_key} } = $value; - - next if defined $::form->{$ref->{sess_key}}; - - my $data = $value->get; - $::form->{$ref->{sess_key}} = $data if $value->{auto_restore} || !ref $data; + if ($ref->{auto_restore} || $auto_restore_keys{$ref->{sess_key}}) { + my $value = SL::Auth::SessionValue->new(auth => $self, + key => $ref->{sess_key}, + value => $ref->{sess_value}, + auto_restore => $ref->{auto_restore}, + raw => 1); + $self->{SESSION}->{ $ref->{sess_key} } = $value; + + next if defined $::form->{$ref->{sess_key}}; + + my $data = $value->get; + $::form->{$ref->{sess_key}} = $data if $value->{auto_restore} || !ref $data; + } else { + my $value = SL::Auth::SessionValue->new(auth => $self, + key => $ref->{sess_key}); + $self->{SESSION}->{ $ref->{sess_key} } = $value; + } } $sth->finish; - - $query = <fetchrow_hashref) { - my $value = SL::Auth::SessionValue->new(auth => $self, - key => $ref->{sess_key}); - $self->{SESSION}->{ $ref->{sess_key} } = $value; - } } sub destroy_session { @@ -918,7 +935,7 @@ sub _tables_present { my ($count) = selectrow_query($main::form, $dbh, $query, @tables); - return scalar @tables == $count; + scalar @tables == $count; } } @@ -936,7 +953,7 @@ sub all_rights_full { my ($self) = @_; @{ $self->{master_rights} ||= do { - $self->dbconnect->selectall_arrayref("SELECT name, description, category FROM auth.master_rights ORDER BY id"); + $self->dbconnect->selectall_arrayref("SELECT name, description, category FROM auth.master_rights ORDER BY position"); } } } @@ -1060,23 +1077,36 @@ sub evaluate_rights_ary { my $value = 0; my $action = '|'; + my $negate = 0; foreach my $el (@{$ary}) { if (ref $el eq "ARRAY") { + my $val = evaluate_rights_ary($el); + $val = !$val if $negate; + $negate = 0; if ($action eq '|') { - $value |= evaluate_rights_ary($el); + $value |= $val; } else { - $value &= evaluate_rights_ary($el); + $value &= $val; } } elsif (($el eq '&') || ($el eq '|')) { $action = $el; + } elsif ($el eq '!') { + $negate = !$negate; + } elsif ($action eq '|') { - $value |= $el; + my $val = $el; + $val = !$val if $negate; + $negate = 0; + $value |= $val; } else { - $value &= $el; + my $val = $el; + $val = !$val if $negate; + $negate = 0; + $value &= $val; } } @@ -1120,7 +1150,7 @@ sub _parse_rights_string { push @{$cur_ary}, $token; } else { - push @{$cur_ary}, $self->{RIGHTS}->{$login}->{$token} * 1; + push @{$cur_ary}, ($self->{RIGHTS}->{$login}->{$token} // 0) * 1; } } @@ -1292,6 +1322,11 @@ close the database connection. Creating a new database handle on each request can take up to 30% of the pre-request startup time, so we want to avoid that for fast ajax calls. +=item C + +Checks if current user has the C<$right>. If C<$dont_abort> is falsish +the request dies with a access denied error, otherwise returns true or false. + =back =head1 BUGS