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