3 %# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
5 %# (Except where explictly superceded by other copyright notices)
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
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.
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.
26 # Roll back any dangling transactions from a previous failed connection
27 $RT::Handle->ForceRollback() if $RT::Handle->TransactionDepth;
30 local *session unless $m->is_subrequest; # avoid reentrancy, as suggested by masonbook
32 # Disable AutoFlush using an attribute
33 if ($m->request_comp->attr_exists('AutoFlush')) {
34 $m->autoflush($m->request_comp->attr('AutoFlush'));
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
42 ? Encode::decode(utf8 => $_, Encode::FB_PERLQQ) :
44 ? [ map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } @$_ ] :
46 ? { map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } %$_ } : $_
51 $m->{'rt_base_time'} = [Time::HiRes::gettimeofday()];
55 $m->{'rt_base_time'} = time;
57 $m->comp('/Elements/SetupSessionCookie', %ARGS);
59 unless ($session{'CurrentUser'} && $session{'CurrentUser'}->Id) {
60 $session{'CurrentUser'} = RT::CurrentUser->new();
63 # Set the proper encoding for the current language handle
64 $r->content_type("text/html; charset=utf-8");
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/')
74 # If RT is configured for external auth, let's go through and get REMOTE_USER
75 elsif ( $RT::WebExternalAuth ) {
77 # do we actually have a REMOTE_USER equivlent?
78 if ( RT::Interface::Web::WebCanonicalizeInfo() ) {
80 my $orig_user = $user;
82 $user = RT::Interface::Web::WebCanonicalizeInfo();
83 $session{'CurrentUser'} = RT::CurrentUser->new();
84 my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
86 if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
87 my $NodeName = Win32::NodeName();
88 $user =~ s/^\Q$NodeName\E\\//i;
91 $session{'CurrentUser'}->$load_method($user);
93 if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
94 # Create users on-the-fly
96 my $UserObj = RT::User->new(RT::CurrentUser->new('root'));
98 my ($val, $msg) = $UserObj->Create(
99 %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
106 # now get user specific information, to better create our user.
107 my $new_user_info = RT::Interface::Web::WebExternalAutoInfo($user);
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 $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'NewUser');
122 my $method = "Set$attribute";
123 $UserObj->$method($new_user_info->{$attribute})
124 if( defined $new_user_info->{$attribute} );
126 $session{'CurrentUser'}->Load($user);
129 # we failed to successfully create the user. abort abort abort.
130 delete $session{'CurrentUser'};
131 $m->abort() unless $RT::WebFallbackToInternalAuth;
132 $m->comp('/Elements/Login', %ARGS,
133 Error=> loc('Cannot create user: [_1]', $msg));
137 unless ( $session{'CurrentUser'}->Id() ) {
138 delete $session{'CurrentUser'};
141 if ( $RT::WebExternalOnly ) {
142 $m->comp('/Elements/Login', %ARGS,
143 Error=> loc('You are not an authorized user'));
148 elsif ($RT::WebFallbackToInternalAuth) {
149 unless (defined($session{'CurrentUser'})) {
150 $m->comp('/Elements/Login', %ARGS,
151 Error=> loc('XXX CHANGEME You are not an authorized user'));
155 # WebExternalAuth is set, but we don't have a REMOTE_USER. abort
156 delete $session{'CurrentUser'} if defined $session{'CurrentUser'};
160 delete $session{'CurrentUser'}
161 unless $session{'CurrentUser'} and defined $session{'CurrentUser'}->Id;
164 # Process per-page authentication callbacks
165 $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'Auth');
167 # If the user is logging in, let's authenticate
168 if (!$session{'CurrentUser'} && defined ($user) && defined ($pass) ){
169 $session{'CurrentUser'} = RT::CurrentUser->new();
170 $session{'CurrentUser'}->Load($user);
172 if (!$session{'CurrentUser'}->id() ||
173 !$session{'CurrentUser'}->IsPassword($pass))
175 $RT::Logger->error("FAILED LOGIN for $user from $ENV{'REMOTE_ADDR'}");
176 delete $session{'CurrentUser'};
177 $m->comp('/Elements/Login', %ARGS,
178 Error => loc('Your username or password is incorrect'));
182 $RT::Logger->info("Successful login for $user from $ENV{'REMOTE_ADDR'}");
186 # If we've got credentials, let's serve the file up.
187 if ( (defined $session{'CurrentUser'}) and
188 ( $session{'CurrentUser'}->Id) ) {
190 # Process per-page global callbacks
191 $m->comp('/Elements/Callback', %ARGS);
193 # If the user isn't privileged, they can only see SelfService
194 if ((! $session{'CurrentUser'}->Privileged) and
195 ($m->base_comp->path !~ '^(/+)SelfService/') ) {
196 $m->comp('/SelfService/index.html');
200 $m->call_next(%ARGS);
204 # If we have no credentials
206 $m->comp('/Elements/Login', %ARGS);
210 <& /Elements/Footer, %ARGS &>