]> wagnertech.de Git - kivitendo-erp.git/commitdiff
Dispatcher: Auch Controller ermöglichen, die Admin-Login benötigen
authorMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 17 Aug 2012 10:24:58 +0000 (12:24 +0200)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 17 Aug 2012 10:24:58 +0000 (12:24 +0200)
Default ist für Controller, dass all ihre Funktionen User-Logins
benötigen. Kann ein Controller ändern, indem er die Sub
"get_auth_level" überschreibt (siehe Doku in
SL::Contrller::Base). Dies schafft die Basis dafür, auch Admin-Dinge
in der neuen Controller-Architektur zu implementieren.

Für die Zukunft kann man leicht ein weiteres Level neben 'user' und
'admin' einbauen, z.B. 'none' für Actions, die definitiv kein Login
benötigen.

Funktionierendes Beispiel für einen solchen Controller (Aufruf dann
über URL ".../controller.pl?action=AdminTest/proof_of_concept"):

package SL::Controller::AdminTest;

use strict;

use parent qw(SL::Controller::Base);

use Rose::Object::MakeMethods::Generic
(
 scalar => [ qw(business) ],
);

#
# actions
#

sub action_proof_of_concept {
  my ($self) = @_;

  $::form->header;
  print $self->render(<<EOHTML, { inline => 1 });
 <body>
  <p>I've been called with an ADMIN login only!</p>
 </body>
</html>
EOHTML
}

#
# overrides
#

sub get_auth_level {
  return 'admin';
}

1;

SL/Controller/Base.pm
SL/Dispatcher.pm
SL/Dispatcher/AuthHandler.pm [new file with mode: 0644]
SL/Dispatcher/AuthHandler/Admin.pm [new file with mode: 0644]
SL/Dispatcher/AuthHandler/User.pm [new file with mode: 0644]
templates/webpages/login/password_error.html

index ac09057af1c279bfcf000604bc46d102c3d06728..c8713950c2d2415d6935d43fc8879809d1d1d2dd 100644 (file)
@@ -167,6 +167,11 @@ sub delay_flash_on_redirect {
   0;
 }
 
+sub get_auth_level {
+  # Ignore the 'action' parameter.
+  return 'user';
+}
+
 #
 # private functions -- for use in Base only
 #
@@ -503,6 +508,15 @@ May be overridden by a controller. If this method returns true, redirect_to
 will delay all flash messages for the current request. Defaults to false for
 compatibility reasons.
 
+=item C<get_auth_level $action>
+
+May be overridden by a controller. Determines what kind of
+authentication is required for a particular action. Must return either
+C<admin> (which means that authentication as an admin is required),
+C<user> (authentication as a normal user suffices) with a possible
+future value C<none> (which would require no authentication but is not
+yet implemented).
+
 =back
 
 =head2 PRIVATE FUNCTIONS
index 21398ccca72671947e279bd6a228a926b32c06d4..8301e56029d903500985df9efe00bf50e8858e7f 100644 (file)
@@ -17,6 +17,7 @@ use List::MoreUtils qw(all);
 use List::Util qw(first);
 use POSIX;
 use SL::Auth;
+use SL::Dispatcher::AuthHandler;
 use SL::LXDebug;
 use SL::LxOfficeConf;
 use SL::Locale;
@@ -37,6 +38,7 @@ sub new {
 
   my $self           = bless {}, $class;
   $self->{interface} = lc($interface || 'cgi');
+  $self->{auth_handler} = SL::Dispatcher::AuthHandler->new;
 
   return $self;
 }
@@ -63,6 +65,7 @@ sub show_error {
   $::lxdebug->enter_sub;
   my $template             = shift;
   my $error_type           = shift || '';
+  my %params               = @_;
 
   $::locale                = Locale->new($::lx_office_conf{system}->{language});
   $::form->{error}         = $::locale->text('The session is invalid or has expired.') if ($error_type eq 'session');
@@ -70,7 +73,7 @@ sub show_error {
   $::myconfig{countrycode} = $::lx_office_conf{system}->{language};
 
   $::form->header;
-  print $::form->parse_html_template($template);
+  print $::form->parse_html_template($template, \%params);
   $::lxdebug->leave_sub;
 
   ::end_of_request();
@@ -143,10 +146,11 @@ sub require_main_code {
 sub _require_controller {
   my $controller =  shift;
   $controller    =~ s|[^A-Za-z0-9_]||g;
+  $controller    =  "SL/Controller/${controller}";
 
   eval {
     package main;
-    require "SL/Controller/${controller}.pm";
+    require "${controller}.pm";
   } or die $EVAL_ERROR;
 }
 
@@ -163,8 +167,6 @@ sub handle_request {
 
   my ($script, $path, $suffix, $script_name, $action, $routing_type);
 
-  $script_name = $ENV{SCRIPT_NAME};
-
   $self->unrequire_bin_mozilla;
 
   $::locale        = Locale->new($::lx_office_conf{system}->{language});
@@ -177,7 +179,7 @@ sub handle_request {
 
   $::form->read_cgi_input;
 
-  eval { ($routing_type, $script_name, $action) = _route_request($script_name); 1; } or return;
+  eval { ($routing_type, $script_name, $action) = _route_request($ENV{SCRIPT_NAME}); 1; } or return;
 
   if ($routing_type eq 'old') {
     $::form->{action}  =  lc $::form->{action};
@@ -205,23 +207,15 @@ sub handle_request {
     } else {
       show_error('login/password_error', 'session') if SL::Auth::SESSION_EXPIRED == $session_result;
 
-      my $login = $::auth->get_session_value('login');
-      show_error('login/password_error', 'password') if not defined $login;
-
-      %::myconfig = $::auth->read_user(login => $login);
-
-      show_error('login/password_error', 'password') unless $::myconfig{login};
-
-      $::locale = Locale->new($::myconfig{countrycode});
-
-      show_error('login/password_error', 'password') if SL::Auth::OK != $::auth->authenticate($login, undef);
-
-      $::auth->create_or_refresh_session;
-      $::auth->delete_session_value('FLASH');
-      delete $::form->{password};
+      my $auth_level = $self->{auth_handler}->handle(
+        routing_type => $routing_type,
+        script       => $script,
+        controller   => $script_name,
+        action       => $action,
+      );
 
       if ($action) {
-        $::instance_conf->init;
+        $::instance_conf->init if $auth_level eq 'user';
 
         map { $::form->{$_} = $::myconfig{$_} } qw(charset)
           unless $action eq 'save' && $::form->{type} eq 'preferences';
diff --git a/SL/Dispatcher/AuthHandler.pm b/SL/Dispatcher/AuthHandler.pm
new file mode 100644 (file)
index 0000000..60dc637
--- /dev/null
@@ -0,0 +1,32 @@
+package SL::Dispatcher::AuthHandler;
+
+use strict;
+
+use parent qw(Rose::Object);
+
+use SL::Dispatcher::AuthHandler::Admin;
+use SL::Dispatcher::AuthHandler::User;
+
+sub handle {
+  my ($self, %param) = @_;
+
+  my $auth_level                       = $self->get_auth_level(%param);
+  my $handler_name                     = "SL::Dispatcher::AuthHandler::" . ucfirst($auth_level);
+  $self->{handlers}                  ||= {};
+  $self->{handlers}->{$handler_name} ||= $handler_name->new;
+  $self->{handlers}->{$handler_name}->handle;
+
+  return $auth_level;
+}
+
+sub get_auth_level {
+  my ($self, %param) = @_;
+
+  my $auth_level = $param{routing_type} eq 'old'        ? ($param{script} eq 'admin' ? 'admin' : 'user')
+                 : $param{routing_type} eq 'controller' ? "SL::Controller::$param{controller}"->get_auth_level($param{action})
+                 :                                        'user';
+
+  return $auth_level eq 'user' ? 'user' : 'admin';
+}
+
+1;
diff --git a/SL/Dispatcher/AuthHandler/Admin.pm b/SL/Dispatcher/AuthHandler/Admin.pm
new file mode 100644 (file)
index 0000000..5a92015
--- /dev/null
@@ -0,0 +1,16 @@
+package SL::Dispatcher::AuthHandler::Admin;
+
+use strict;
+
+use parent qw(Rose::Object);
+
+sub handle {
+  %::myconfig = ();
+
+  return if $::auth->authenticate_root($::auth->get_session_value('rpw')) == $::auth->OK();
+
+  $::auth->delete_session_value('rpw');
+  SL::Dispatcher::show_error('login/password_error', 'password', is_admin => 1);
+}
+
+1;
diff --git a/SL/Dispatcher/AuthHandler/User.pm b/SL/Dispatcher/AuthHandler/User.pm
new file mode 100644 (file)
index 0000000..13d6448
--- /dev/null
@@ -0,0 +1,24 @@
+package SL::Dispatcher::AuthHandler::User;
+
+use strict;
+
+use parent qw(Rose::Object);
+
+sub handle {
+  my $login = $::auth->get_session_value('login');
+  SL::Dispatcher::show_error('login/password_error', 'password') if not defined $login;
+
+  %::myconfig = $::auth->read_user(login => $login);
+
+  SL::Dispatcher::show_error('login/password_error', 'password') unless $::myconfig{login};
+
+  $::locale = Locale->new($::myconfig{countrycode});
+
+  SL::Dispatcher::show_error('login/password_error', 'password') if SL::Auth::OK != $::auth->authenticate($login, undef);
+
+  $::auth->create_or_refresh_session;
+  $::auth->delete_session_value('FLASH');
+  delete $::form->{password};
+}
+
+1;
index e1060a0156410f53ab7f6026bb42e1e953cc9b5a..1ee8ec83054c0cf500f95408cc655bca9777076d 100644 (file)
@@ -5,7 +5,7 @@
 
  <p>[% error %]</p>
 
- <p><a href="login.pl" target="_top">[% 'Login' | $T8 %]</a></p>
+ <p><a href="[% IF is_admin %]admin.pl[% ELSE %]login.pl[% END %]" target="_top">[% 'Login' | $T8 %]</a></p>
 
 </body>
 </html>