This commit was generated by cvs2svn to compensate for changes in r4407,
[freeside.git] / rt / html / autohandler
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %# 
3 %# COPYRIGHT:
4 %#  
5 %# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC 
6 %#                                          <jesse@bestpractical.com>
7 %# 
8 %# (Except where explicitly superseded by other copyright notices)
9 %# 
10 %# 
11 %# LICENSE:
12 %# 
13 %# This work is made available to you under the terms of Version 2 of
14 %# the GNU General Public License. A copy of that license should have
15 %# been provided with this software, but in any event can be snarfed
16 %# from www.gnu.org.
17 %# 
18 %# This work is distributed in the hope that it will be useful, but
19 %# WITHOUT ANY WARRANTY; without even the implied warranty of
20 %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 %# General Public License for more details.
22 %# 
23 %# You should have received a copy of the GNU General Public License
24 %# along with this program; if not, write to the Free Software
25 %# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 %# 
27 %# 
28 %# CONTRIBUTION SUBMISSION POLICY:
29 %# 
30 %# (The following paragraph is not intended to limit the rights granted
31 %# to you to modify and distribute this software under the terms of
32 %# the GNU General Public License and is only of importance to you if
33 %# you choose to contribute your changes and enhancements to the
34 %# community by submitting them to Best Practical Solutions, LLC.)
35 %# 
36 %# By intentionally submitting any modifications, corrections or
37 %# derivatives to this work, or any other work intended for use with
38 %# Request Tracker, to Best Practical Solutions, LLC, you confirm that
39 %# you are the copyright holder for those contributions and you grant
40 %# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
41 %# royalty-free, perpetual, license to use, copy, create derivative
42 %# works based on those contributions, and sublicense and distribute
43 %# those contributions and any derivatives thereof.
44 %# 
45 %# END BPS TAGGED BLOCK }}}
46 <%INIT>
47
48 # Roll back any dangling transactions from a previous failed connection
49 $RT::Handle->ForceRollback() if $RT::Handle->TransactionDepth;
50
51
52 local *session unless $m->is_subrequest; # avoid reentrancy, as suggested by masonbook
53
54 # Disable AutoFlush using an attribute
55 if ($m->request_comp->attr_exists('AutoFlush')) {
56     $m->autoflush($m->request_comp->attr('AutoFlush'));
57 }
58
59 %ARGS = map {
60     # if they've passed multiple values, they'll be an array. if they've 
61     # passed just one, a scalar whatever they are, mark them as utf8
62     my $type = ref($_);
63     (!$type)
64         ? Encode::is_utf8($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) :
65         ($type eq 'ARRAY')
66         ? [ map { (ref($_) or Encode::is_utf8($_)) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } @$_ ] :
67         ($type eq 'HASH')
68         ? { map { (ref($_) or Encode::is_utf8($_)) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } %$_ } : $_
69     } %ARGS;
70
71 $m->{'rt_base_time'} = [Time::HiRes::gettimeofday()];
72         
73 $m->comp('/Elements/SetupSessionCookie', %ARGS);
74
75 unless ($session{'CurrentUser'} && $session{'CurrentUser'}->Id) {
76     $session{'CurrentUser'} = RT::CurrentUser->new();
77 }
78
79 # Set the proper encoding for the current language handle
80 $r->content_type("text/html; charset=utf-8");
81
82 # If it's a noauth file, don't ask for auth.
83 if ($m->base_comp->path =~ $RT::WebNoAuthRegex )
84 {
85     $m->call_next(%ARGS);
86     $m->abort();
87 }
88
89 # If RT is configured for external auth, let's go through and get REMOTE_USER
90 elsif ( $RT::WebExternalAuth ) {
91
92     # do we actually have a REMOTE_USER equivlent?
93     if ( RT::Interface::Web::WebCanonicalizeInfo() ) {
94
95         my $orig_user = $user;
96         
97         $user = RT::Interface::Web::WebCanonicalizeInfo();
98         $session{'CurrentUser'} = RT::CurrentUser->new();
99         my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
100         
101         if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
102             my $NodeName = Win32::NodeName();
103             $user =~ s/^\Q$NodeName\E\\//i;
104         }
105         
106         $session{'CurrentUser'}->$load_method($user);
107         
108         if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
109             # Create users on-the-fly
110             
111             my $UserObj = RT::User->new(RT::CurrentUser->new('RT_System'));
112             
113             my ($val, $msg) = $UserObj->Create(
114                                                %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
115                                                Name   => $user,
116                                                Gecos  => $user,
117                                                );
118             
119             if ($val) {
120                 
121                 # now get user specific information, to better create our user.
122                 my $new_user_info = RT::Interface::Web::WebExternalAutoInfo($user);
123                 
124                 # set the attributes that have been defined.
125                 # FIXME: this is a horrible kludge. I'm sure there's something cleaner
126                 foreach my $attribute ('Name', 'Comments', 'Signature', 'EmailAddress',
127                                        'PagerEmailAddress', 'FreeformContactInfo',
128                                        'Organization', 'Disabled', 'Privileged',
129                                        'RealName', 'NickName', 'Lang', 'EmailEncoding',
130                                        'WebEncoding', 'ExternalContactInfoId',
131                                        'ContactInfoSystem', 'ExternalAuthId', 'Gecos',
132                                        'HomePhone', 'WorkPhone', 'MobilePhone',
133                                        'PagerPhone', 'Address1', 'Address2', 'City',
134                                        'State', 'Zip', 'Country') {
135                $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'NewUser');
136                     
137                     my $method = "Set$attribute";
138                     $UserObj->$method($new_user_info->{$attribute}) 
139                         if( defined $new_user_info->{$attribute} );
140                 }           
141                 $session{'CurrentUser'}->Load($user);
142             }
143             else {
144                 # we failed to successfully create the user. abort abort abort.
145                 delete $session{'CurrentUser'};
146                 $m->abort() unless $RT::WebFallbackToInternalAuth;
147                 $m->comp('/Elements/Login', %ARGS, 
148                          Error=> loc('Cannot create user: [_1]', $msg));
149             }
150         }
151         
152         unless ( $session{'CurrentUser'}->Id() ) {
153             delete $session{'CurrentUser'};
154             $user = $orig_user;
155             
156             if ( $RT::WebExternalOnly ) {               
157                 $m->comp('/Elements/Login', %ARGS, 
158                          Error=> loc('You are not an authorized user'));
159                 $m->abort();
160             }
161         }
162     }
163     elsif ($RT::WebFallbackToInternalAuth) {
164         unless (defined($session{'CurrentUser'})) {
165                 $m->comp('/Elements/Login', %ARGS,
166                          Error=> loc('You are not an authorized user'));
167                 $m->abort();
168         }
169     } else {
170         # WebExternalAuth is set, but we don't have a REMOTE_USER. abort
171         delete $session{'CurrentUser'} if defined $session{'CurrentUser'};
172     }
173 }
174
175 delete $session{'CurrentUser'}
176     unless $session{'CurrentUser'} and defined $session{'CurrentUser'}->Id;
177
178
179 # Process per-page authentication callbacks
180 $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'Auth');
181
182 # If the user is logging in, let's authenticate
183 if (!$session{'CurrentUser'} && defined ($user) && defined ($pass) ){
184     $session{'CurrentUser'} = RT::CurrentUser->new();
185     $session{'CurrentUser'}->Load($user);
186
187     if (!$session{'CurrentUser'}->id() ||
188         !$session{'CurrentUser'}->IsPassword($pass))
189     {
190         delete $session{'CurrentUser'};
191         $RT::Logger->error("FAILED LOGIN for $user from $ENV{'REMOTE_ADDR'}");
192         $m->comp('/Elements/Login', %ARGS,
193                  Error => loc('Your username or password is incorrect'));
194         $m->abort();
195     }
196     else {
197         $RT::Logger->info("Successful login for $user from $ENV{'REMOTE_ADDR'}");
198     }
199 }
200   
201 # If we've got credentials, let's serve the file up.
202 if ( (defined $session{'CurrentUser'}) and 
203      ( $session{'CurrentUser'}->Id) ) {
204     
205     # Process per-page global callbacks
206     $m->comp('/Elements/Callback', %ARGS);
207
208     # If the user isn't privileged, they can only see SelfService
209     if ((! $session{'CurrentUser'}->Privileged) and
210         ($m->base_comp->path !~ '^(/+)SelfService/') ) {
211         $m->comp('/SelfService/index.html');
212         $m->abort();
213     }
214     else {
215         $m->call_next(%ARGS);
216     }
217 }
218
219 # If we have no credentials
220 else {
221     $m->comp('/Elements/Login', %ARGS);
222     $m->abort();
223 }
224 </%INIT>
225 <& /Elements/Footer, %ARGS &>
226 <%ARGS>
227 $user => undef
228 $pass => undef
229 $menu => undef
230 </%ARGS>