]>
Commit | Line | Data |
---|---|---|
84fb5b46 MKG |
1 | # BEGIN BPS TAGGED BLOCK {{{ |
2 | # | |
3 | # COPYRIGHT: | |
4 | # | |
5 | # This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC | |
6 | # <sales@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., 51 Franklin Street, Fifth Floor, Boston, MA | |
26 | # 02110-1301 or visit their web page on the internet at | |
27 | # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. | |
28 | # | |
29 | # | |
30 | # CONTRIBUTION SUBMISSION POLICY: | |
31 | # | |
32 | # (The following paragraph is not intended to limit the rights granted | |
33 | # to you to modify and distribute this software under the terms of | |
34 | # the GNU General Public License and is only of importance to you if | |
35 | # you choose to contribute your changes and enhancements to the | |
36 | # community by submitting them to Best Practical Solutions, LLC.) | |
37 | # | |
38 | # By intentionally submitting any modifications, corrections or | |
39 | # derivatives to this work, or any other work intended for use with | |
40 | # Request Tracker, to Best Practical Solutions, LLC, you confirm that | |
41 | # you are the copyright holder for those contributions and you grant | |
42 | # Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, | |
43 | # royalty-free, perpetual, license to use, copy, create derivative | |
44 | # works based on those contributions, and sublicense and distribute | |
45 | # those contributions and any derivatives thereof. | |
46 | # | |
47 | # END BPS TAGGED BLOCK }}} | |
48 | ||
49 | =head1 NAME | |
50 | ||
51 | RT::CurrentUser - an RT object representing the current user | |
52 | ||
53 | =head1 SYNOPSIS | |
54 | ||
55 | use RT::CurrentUser; | |
56 | ||
57 | # laod | |
58 | my $current_user = RT::CurrentUser->new; | |
59 | $current_user->Load(...); | |
60 | # or | |
61 | my $current_user = RT::CurrentUser->new( $user_obj ); | |
62 | # or | |
63 | my $current_user = RT::CurrentUser->new( $address || $name || $id ); | |
64 | ||
65 | # manipulation | |
66 | $current_user->UserObj->SetName('new_name'); | |
67 | ||
68 | ||
69 | =head1 DESCRIPTION | |
70 | ||
71 | B<Read-only> subclass of L<RT::User> class. Used to define the current | |
72 | user. You should pass an instance of this class to constructors of | |
73 | many RT classes, then the instance used to check ACLs and localize | |
74 | strings. | |
75 | ||
76 | =head1 METHODS | |
77 | ||
78 | See also L<RT::User> for a list of methods this class has. | |
79 | ||
80 | =head2 new | |
81 | ||
82 | Returns new CurrentUser object. Unlike all other classes of RT it takes | |
83 | either subclass of C<RT::User> class object or scalar value that is | |
84 | passed to Load method. | |
85 | ||
86 | =cut | |
87 | ||
88 | ||
89 | package RT::CurrentUser; | |
90 | ||
91 | use RT::I18N; | |
92 | ||
93 | use strict; | |
94 | use warnings; | |
95 | ||
96 | ||
97 | use base qw/RT::User/; | |
98 | ||
99 | #The basic idea here is that $self->CurrentUser is always supposed | |
100 | # to be a CurrentUser object. but that's hard to do when we're trying to load | |
101 | # the CurrentUser object | |
102 | ||
103 | sub _Init { | |
104 | my $self = shift; | |
105 | my $User = shift; | |
106 | ||
107 | $self->{'table'} = "Users"; | |
108 | ||
109 | if ( defined $User ) { | |
110 | ||
111 | if ( UNIVERSAL::isa( $User, 'RT::User' ) ) { | |
112 | $self->LoadById( $User->id ); | |
113 | } | |
114 | elsif ( ref $User ) { | |
115 | $RT::Logger->crit( | |
116 | "RT::CurrentUser->new() called with a bogus argument: $User"); | |
117 | } | |
118 | else { | |
119 | $self->Load( $User ); | |
120 | } | |
121 | } | |
122 | ||
123 | $self->_BuildTableAttributes; | |
124 | ||
125 | } | |
126 | ||
127 | =head2 Create, Delete and Set* | |
128 | ||
129 | As stated above it's a subclass of L<RT::User>, but this class is read-only | |
130 | and calls to these methods are illegal. Return 'permission denied' message | |
131 | and log an error. | |
132 | ||
133 | =cut | |
134 | ||
135 | sub Create { | |
136 | my $self = shift; | |
137 | $RT::Logger->error('RT::CurrentUser is read-only, RT::User for manipulation'); | |
138 | return (0, $self->loc('Permission Denied')); | |
139 | } | |
140 | ||
141 | sub Delete { | |
142 | my $self = shift; | |
143 | $RT::Logger->error('RT::CurrentUser is read-only, RT::User for manipulation'); | |
144 | return (0, $self->loc('Permission Denied')); | |
145 | } | |
146 | ||
147 | sub _Set { | |
148 | my $self = shift; | |
149 | $RT::Logger->error('RT::CurrentUser is read-only, RT::User for manipulation'); | |
150 | return (0, $self->loc('Permission Denied')); | |
151 | } | |
152 | ||
153 | =head2 UserObj | |
154 | ||
155 | Returns the L<RT::User> object associated with this CurrentUser object. | |
156 | ||
157 | =cut | |
158 | ||
159 | sub UserObj { | |
160 | my $self = shift; | |
161 | ||
162 | my $user = RT::User->new( $self ); | |
163 | unless ( $user->LoadById( $self->Id ) ) { | |
164 | $RT::Logger->error("Couldn't load " . $self->Id . " from the users database."); | |
165 | } | |
166 | return $user; | |
167 | } | |
168 | ||
169 | sub _CoreAccessible { | |
170 | { | |
171 | Name => { 'read' => 1 }, | |
172 | Gecos => { 'read' => 1 }, | |
173 | RealName => { 'read' => 1 }, | |
174 | Lang => { 'read' => 1 }, | |
175 | Password => { 'read' => 0, 'write' => 0 }, | |
176 | EmailAddress => { 'read' => 1, 'write' => 0 } | |
177 | }; | |
178 | ||
179 | } | |
180 | ||
181 | =head2 LoadByGecos | |
182 | ||
183 | Loads a User into this CurrentUser object. | |
184 | Takes a unix username as its only argument. | |
185 | ||
186 | =cut | |
187 | ||
188 | sub LoadByGecos { | |
189 | my $self = shift; | |
190 | return $self->LoadByCol( "Gecos", shift ); | |
191 | } | |
192 | ||
193 | =head2 LoadByName | |
194 | ||
195 | Loads a User into this CurrentUser object. | |
196 | Takes a Name. | |
197 | ||
198 | =cut | |
199 | ||
200 | sub LoadByName { | |
201 | my $self = shift; | |
202 | return $self->LoadByCol( "Name", shift ); | |
203 | } | |
204 | ||
205 | =head2 LanguageHandle | |
206 | ||
207 | Returns this current user's langauge handle. Should take a language | |
208 | specification. but currently doesn't | |
209 | ||
210 | =cut | |
211 | ||
212 | sub LanguageHandle { | |
213 | my $self = shift; | |
214 | if ( !defined $self->{'LangHandle'} | |
215 | || !UNIVERSAL::can( $self->{'LangHandle'}, 'maketext' ) | |
216 | || @_ ) | |
217 | { | |
218 | if ( my $lang = $self->Lang ) { | |
219 | push @_, $lang; | |
220 | } | |
221 | elsif ( $self->id && ($self->id == (RT->SystemUser->id||0) || $self->id == (RT->Nobody->id||0)) ) { | |
222 | # don't use ENV magic for system users | |
223 | push @_, 'en'; | |
224 | } | |
225 | ||
226 | $self->{'LangHandle'} = RT::I18N->get_handle(@_); | |
227 | } | |
228 | ||
229 | # Fall back to english. | |
230 | unless ( $self->{'LangHandle'} ) { | |
231 | die "We couldn't get a dictionary. Ne mogu naidti slovar. No puedo encontrar dictionario."; | |
232 | } | |
233 | return $self->{'LangHandle'}; | |
234 | } | |
235 | ||
236 | sub loc { | |
237 | my $self = shift; | |
238 | return '' if !defined $_[0] || $_[0] eq ''; | |
239 | ||
240 | my $handle = $self->LanguageHandle; | |
241 | ||
242 | if (@_ == 1) { | |
243 | # pre-scan the lexicon hashes to return _AUTO keys verbatim, | |
244 | # to keep locstrings containing '[' and '~' from tripping over Maketext | |
245 | return $_[0] unless grep exists $_->{$_[0]}, @{ $handle->_lex_refs }; | |
246 | } | |
247 | ||
248 | return $handle->maketext(@_); | |
249 | } | |
250 | ||
251 | sub loc_fuzzy { | |
252 | my $self = shift; | |
253 | return '' if !defined $_[0] || $_[0] eq ''; | |
254 | ||
255 | # XXX: work around perl's deficiency when matching utf8 data | |
256 | return $_[0] if Encode::is_utf8($_[0]); | |
257 | ||
258 | return $self->LanguageHandle->maketext_fuzzy( @_ ); | |
259 | } | |
260 | ||
261 | =head2 CurrentUser | |
262 | ||
263 | Return the current currentuser object | |
264 | ||
265 | =cut | |
266 | ||
267 | sub CurrentUser { | |
268 | return shift; | |
269 | } | |
270 | ||
271 | =head2 Authenticate | |
272 | ||
273 | Takes $password, $created and $nonce, and returns a boolean value | |
274 | representing whether the authentication succeeded. | |
275 | ||
276 | If both $nonce and $created are specified, validate $password against: | |
277 | ||
278 | encode_base64(sha1( | |
279 | $nonce . | |
280 | $created . | |
281 | sha1_hex( "$username:$realm:$server_pass" ) | |
282 | )) | |
283 | ||
284 | where $server_pass is the md5_hex(password) digest stored in the | |
285 | database, $created is in ISO time format, and $nonce is a random | |
286 | string no longer than 32 bytes. | |
287 | ||
288 | =cut | |
289 | ||
290 | sub Authenticate { | |
291 | my ($self, $password, $created, $nonce, $realm) = @_; | |
292 | ||
293 | require Digest::MD5; | |
294 | require Digest::SHA1; | |
295 | require MIME::Base64; | |
296 | ||
297 | my $username = $self->UserObj->Name or return; | |
298 | my $server_pass = $self->UserObj->__Value('Password') or return; | |
299 | my $auth_digest = MIME::Base64::encode_base64(Digest::SHA1::sha1( | |
300 | $nonce . | |
301 | $created . | |
302 | Digest::MD5::md5_hex("$username:$realm:$server_pass") | |
303 | )); | |
304 | ||
305 | chomp($password); | |
306 | chomp($auth_digest); | |
307 | ||
308 | return ($password eq $auth_digest); | |
309 | } | |
310 | ||
311 | RT::Base->_ImportOverlays(); | |
312 | ||
313 | 1; |