This commit was generated by cvs2svn to compensate for changes in r3921,
[freeside.git] / rt / html / autohandler
index ce8b756..b21d261 100644 (file)
@@ -1,8 +1,14 @@
-%# BEGIN LICENSE BLOCK
+%# {{{ BEGIN BPS TAGGED BLOCK
 %# 
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%# COPYRIGHT:
+%#  
+%# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC 
+%#                                          <jesse@bestpractical.com>
 %# 
-%# (Except where explictly superceded by other copyright notices)
+%# (Except where explicitly superseded by other copyright notices)
+%# 
+%# 
+%# LICENSE:
 %# 
 %# This work is made available to you under the terms of Version 2 of
 %# the GNU General Public License. A copy of that license should have
 %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 %# General Public License for more details.
 %# 
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%# 
+%# 
+%# CONTRIBUTION SUBMISSION POLICY:
 %# 
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
 %# 
-%# END LICENSE BLOCK
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%# 
+%# }}} END BPS TAGGED BLOCK
 <%INIT>
 
 # Roll back any dangling transactions from a previous failed connection
 $RT::Handle->ForceRollback() if $RT::Handle->TransactionDepth;
 
 
-local *session;
+local *session unless $m->is_subrequest; # avoid reentrancy, as suggested by masonbook
+
+# Disable AutoFlush using an attribute
+if ($m->request_comp->attr_exists('AutoFlush')) {
+    $m->autoflush($m->request_comp->attr('AutoFlush'));
+}
+
 %ARGS = map {
-    # if they've passed multiple values, they'll be an array. if they've passed just one, a scalar
-    # whatever they are, mark them as utf8
+    # if they've passed multiple values, they'll be an array. if they've 
+    # passed just one, a scalar whatever they are, mark them as utf8
     my $type = ref($_);
     (!$type)
        ? Encode::decode(utf8 => $_, Encode::FB_PERLQQ) :
-    ($type eq 'ARRAY')
+       ($type eq 'ARRAY')
        ? [ map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } @$_ ] :
-    ($type eq 'HASH')
+       ($type eq 'HASH')
        ? { map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } %$_ } : $_
-} %ARGS;
+    } %ARGS;
 
 if ($ARGS{'Debug'}) {
         require Time::HiRes;
@@ -58,76 +86,102 @@ unless ($session{'CurrentUser'} && $session{'CurrentUser'}->Id) {
 $r->content_type("text/html; charset=utf-8");
 
 # If it's a noauth file, don't ask for auth.
-if ($m->base_comp->path =~ '^/+NoAuth/' ||
-    $m->base_comp->path =~ '^/+REST/\d+\.\d+/NoAuth/')
+if ($m->base_comp->path =~ $RT::WebNoAuthRegex )
 {
     $m->call_next(%ARGS);
     $m->abort();
 }
 
-# If RT is configured for external auth, let's get REMOTE_USER
-elsif ($RT::WebExternalAuth and length($ENV{'REMOTE_USER'})) {
-    my $orig_user = $user;
-
-    $user = $ENV{'REMOTE_USER'};
-    $session{'CurrentUser'} = RT::CurrentUser->new();
-    my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
-    
-    if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
-       my $NodeName = Win32::NodeName();
-       $user =~ s/^\Q$NodeName\E\\//i;
-    }
-
-    $session{'CurrentUser'}->$load_method($user);
-
-    if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
-       # Create users on-the-fly with default attributes
-
-       my $UserObj = RT::User->new(RT::CurrentUser->new('root'));
-
-       my ($val, $msg) = $UserObj->Create(
-           %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
-           Name         => $user,
-           Gecos        => $user,
-       );
-
-       if ($val) {
-           $UserObj->SetPrivileged(1);
-
-           if ($^O !~ /^(?:riscos|MacOS|MSWin32|dos|os2)$/) {
-               # Populate fields with information from Unix /etc/passwd
-
-               my ($comments, $realname) = (getpwnam($user))[5, 6];
-               $UserObj->SetComments($comments) if defined $comments;
-               $UserObj->SetRealName($realname) if defined $realname;
+# If RT is configured for external auth, let's go through and get REMOTE_USER
+elsif ( $RT::WebExternalAuth ) {
+
+    # do we actually have a REMOTE_USER equivlent?
+    if ( RT::Interface::Web::WebCanonicalizeInfo() ) {
+
+       my $orig_user = $user;
+       
+       $user = RT::Interface::Web::WebCanonicalizeInfo();
+       $session{'CurrentUser'} = RT::CurrentUser->new();
+       my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
+       
+       if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
+           my $NodeName = Win32::NodeName();
+           $user =~ s/^\Q$NodeName\E\\//i;
+       }
+       
+       $session{'CurrentUser'}->$load_method($user);
+       
+       if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
+           # Create users on-the-fly
+           
+           my $UserObj = RT::User->new(RT::CurrentUser->new('RT_System'));
+           
+           my ($val, $msg) = $UserObj->Create(
+                                              %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
+                                              Name   => $user,
+                                              Gecos  => $user,
+                                              );
+           
+           if ($val) {
+               
+               # now get user specific information, to better create our user.
+               my $new_user_info = RT::Interface::Web::WebExternalAutoInfo($user);
+               
+               # set the attributes that have been defined.
+               # FIXME: this is a horrible kludge. I'm sure there's something cleaner
+               foreach my $attribute ('Name', 'Comments', 'Signature', 'EmailAddress',
+                                      'PagerEmailAddress', 'FreeformContactInfo',
+                                      'Organization', 'Disabled', 'Privileged',
+                                      'RealName', 'NickName', 'Lang', 'EmailEncoding',
+                                      'WebEncoding', 'ExternalContactInfoId',
+                                      'ContactInfoSystem', 'ExternalAuthId', 'Gecos',
+                                      'HomePhone', 'WorkPhone', 'MobilePhone',
+                                      'PagerPhone', 'Address1', 'Address2', 'City',
+                                      'State', 'Zip', 'Country') {
+               $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'NewUser');
+                   
+                   my $method = "Set$attribute";
+                   $UserObj->$method($new_user_info->{$attribute}) 
+                       if( defined $new_user_info->{$attribute} );
+               }           
+               $session{'CurrentUser'}->Load($user);
            }
-           elsif ($^O eq 'MSWin32' and eval 'use Net::AdminMisc; 1') {
-               # Populate fields with information from NT domain controller
+           else {
+               # we failed to successfully create the user. abort abort abort.
+               delete $session{'CurrentUser'};
+               $m->abort() unless $RT::WebFallbackToInternalAuth;
+               $m->comp('/Elements/Login', %ARGS, 
+                        Error=> loc('Cannot create user: [_1]', $msg));
            }
-
-           $session{'CurrentUser'}->Load($user);
        }
-       else {
+       
+       unless ( $session{'CurrentUser'}->Id() ) {
            delete $session{'CurrentUser'};
-           $m->abort() unless $RT::WebFallbackToInternalAuth;
-           $m->comp('/Elements/Login', %ARGS, Error=> loc('Cannot create user: [_1]', $msg));
+           $user = $orig_user;
+           
+           if ( $RT::WebExternalOnly ) {               
+               $m->comp('/Elements/Login', %ARGS, 
+                        Error=> loc('You are not an authorized user'));
+               $m->abort();
+           }
        }
     }
-
-    unless ( $session{'CurrentUser'}->Id() ) {
-        delete $session{'CurrentUser'};
-        $user = $orig_user;
-
-       if ( $RT::WebExternalOnly ) {           
-           $m->comp('/Elements/Login', %ARGS, Error=> loc('You are not an authorized user'));
-           $m->abort();
+    elsif ($RT::WebFallbackToInternalAuth) {
+       unless (defined($session{'CurrentUser'})) {
+               $m->comp('/Elements/Login', %ARGS,
+                         Error=> loc('XXX CHANGEME You are not an authorized user'));
+                $m->abort();
        }
+    } else {
+       # WebExternalAuth is set, but we don't have a REMOTE_USER. abort
+       delete $session{'CurrentUser'} if defined $session{'CurrentUser'};
     }
 }
 
 delete $session{'CurrentUser'}
     unless $session{'CurrentUser'} and defined $session{'CurrentUser'}->Id;
 
+
 # Process per-page authentication callbacks
 $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'Auth');
 
@@ -139,11 +193,15 @@ if (!$session{'CurrentUser'} && defined ($user) && defined ($pass) ){
     if (!$session{'CurrentUser'}->id() ||
         !$session{'CurrentUser'}->IsPassword($pass))
     {
+       $RT::Logger->error("FAILED LOGIN for $user from $ENV{'REMOTE_ADDR'}");
         delete $session{'CurrentUser'};
         $m->comp('/Elements/Login', %ARGS,
                  Error => loc('Your username or password is incorrect'));
         $m->abort();
     }
+    else {
+       $RT::Logger->info("Successful login for $user from $ENV{'REMOTE_ADDR'}");
+    }
 }
   
 # If we've got credentials, let's serve the file up.