← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:26:33 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Users/BaseUserMapping.pm
StatementsExecuted 39637 statements in 122ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
122253388.4ms88.4msFoswiki::Users::BaseUserMapping::::isGroupFoswiki::Users::BaseUserMapping::isGroup
515225.49ms5.49msFoswiki::Users::BaseUserMapping::::handlesUserFoswiki::Users::BaseUserMapping::handlesUser
1111.66ms1.80msFoswiki::Users::BaseUserMapping::::BEGIN@33Foswiki::Users::BaseUserMapping::BEGIN@33
60111.08ms1.50msFoswiki::Users::BaseUserMapping::::findUserByWikiNameFoswiki::Users::BaseUserMapping::findUserByWikiName
111167µs186µsFoswiki::Users::BaseUserMapping::::newFoswiki::Users::BaseUserMapping::new
11194µs107µsFoswiki::Users::BaseUserMapping::::finishFoswiki::Users::BaseUserMapping::finish
32270µs132µsFoswiki::Users::BaseUserMapping::::eachGroupMemberFoswiki::Users::BaseUserMapping::eachGroupMember
11131µs40µsFoswiki::Users::BaseUserMapping::::BEGIN@30Foswiki::Users::BaseUserMapping::BEGIN@30
11126µs234µsFoswiki::Users::BaseUserMapping::::isAdminFoswiki::Users::BaseUserMapping::isAdmin
11118µs40µsFoswiki::Users::BaseUserMapping::::BEGIN@31Foswiki::Users::BaseUserMapping::BEGIN@31
11118µs56µsFoswiki::Users::BaseUserMapping::::BEGIN@36Foswiki::Users::BaseUserMapping::BEGIN@36
1119µs9µsFoswiki::Users::BaseUserMapping::::BEGIN@37Foswiki::Users::BaseUserMapping::BEGIN@37
0000s0sFoswiki::Users::BaseUserMapping::::__ANON__[:340]Foswiki::Users::BaseUserMapping::__ANON__[:340]
0000s0sFoswiki::Users::BaseUserMapping::::checkPasswordFoswiki::Users::BaseUserMapping::checkPassword
0000s0sFoswiki::Users::BaseUserMapping::::eachGroupFoswiki::Users::BaseUserMapping::eachGroup
0000s0sFoswiki::Users::BaseUserMapping::::eachMembershipFoswiki::Users::BaseUserMapping::eachMembership
0000s0sFoswiki::Users::BaseUserMapping::::eachUserFoswiki::Users::BaseUserMapping::eachUser
0000s0sFoswiki::Users::BaseUserMapping::::getEmailsFoswiki::Users::BaseUserMapping::getEmails
0000s0sFoswiki::Users::BaseUserMapping::::getLoginNameFoswiki::Users::BaseUserMapping::getLoginName
0000s0sFoswiki::Users::BaseUserMapping::::getWikiNameFoswiki::Users::BaseUserMapping::getWikiName
0000s0sFoswiki::Users::BaseUserMapping::::groupAllowsChangeFoswiki::Users::BaseUserMapping::groupAllowsChange
0000s0sFoswiki::Users::BaseUserMapping::::login2cUIDFoswiki::Users::BaseUserMapping::login2cUID
0000s0sFoswiki::Users::BaseUserMapping::::loginTemplateNameFoswiki::Users::BaseUserMapping::loginTemplateName
0000s0sFoswiki::Users::BaseUserMapping::::passwordErrorFoswiki::Users::BaseUserMapping::passwordError
0000s0sFoswiki::Users::BaseUserMapping::::setPasswordFoswiki::Users::BaseUserMapping::setPassword
0000s0sFoswiki::Users::BaseUserMapping::::userExistsFoswiki::Users::BaseUserMapping::userExists
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+ package Foswiki::Users::BaseUserMapping
6
7User mapping is the process by which Foswiki maps from a username
8(a login name)
9to a display name and back. It is also where groups are maintained.
10
11The BaseMapper provides support for a small number of predefined users.
12No registration - this is a read only usermapper. It uses the mapper
13prefix 'BaseUserMapping_'.
14
15---++ Users
16 * $Foswiki::cfg{AdminUserLogin} - uses the password that
17 was set in Configure (IF its not null)
18 * $Foswiki::cfg{DefaultUserLogin} - WikiGuest
19 * UnknownUser
20 * ProjectContributor
21 * $Foswiki::cfg{Register}{RegistrationAgentWikiName}
22
23---+++ Groups
24 * $Foswiki::cfg{SuperAdminGroup}
25 * BaseGroup
26
27=cut
28
29package Foswiki::Users::BaseUserMapping;
30249µs249µs
# spent 40µs (31+9) within Foswiki::Users::BaseUserMapping::BEGIN@30 which was called: # once (31µs+9µs) by Foswiki::Users::new at line 30
use strict;
# spent 40µs making 1 call to Foswiki::Users::BaseUserMapping::BEGIN@30 # spent 9µs making 1 call to strict::import
31247µs261µs
# spent 40µs (18+21) within Foswiki::Users::BaseUserMapping::BEGIN@31 which was called: # once (18µs+21µs) by Foswiki::Users::new at line 31
use warnings;
# spent 40µs making 1 call to Foswiki::Users::BaseUserMapping::BEGIN@31 # spent 21µs making 1 call to warnings::import
32
332234µs11.80ms
# spent 1.80ms (1.66+134µs) within Foswiki::Users::BaseUserMapping::BEGIN@33 which was called: # once (1.66ms+134µs) by Foswiki::Users::new at line 33
use Foswiki::UserMapping ();
# spent 1.80ms making 1 call to Foswiki::Users::BaseUserMapping::BEGIN@33
34111µsour @ISA = ('Foswiki::UserMapping');
35
36245µs294µs
# spent 56µs (18+38) within Foswiki::Users::BaseUserMapping::BEGIN@36 which was called: # once (18µs+38µs) by Foswiki::Users::new at line 36
use Assert;
# spent 56µs making 1 call to Foswiki::Users::BaseUserMapping::BEGIN@36 # spent 38µs making 1 call to Assert::import
3722.29ms19µs
# spent 9µs within Foswiki::Users::BaseUserMapping::BEGIN@37 which was called: # once (9µs+0s) by Foswiki::Users::new at line 37
use Error ();
# spent 9µs making 1 call to Foswiki::Users::BaseUserMapping::BEGIN@37
38
3912µsour $DEFAULT_USER_CUID = 'BaseUserMapping_666';
4011µsour $UNKNOWN_USER_CUID = 'BaseUserMapping_999';
4111µsour %BASE_USERS;
421800nsour %BASE_GROUPS;
43
44=begin TML
45
46---++ ClassMethod new ($session)
47
48Construct the BaseUserMapping object
49
50=cut
51
52# Constructs a new user mapping handler of this type, referring to $session
53# for any required Foswiki services.
54
# spent 186µs (167+19) within Foswiki::Users::BaseUserMapping::new which was called: # once (167µs+19µs) by Foswiki::Users::new at line 92 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm
sub new {
5547164µs my ( $class, $session ) = @_;
56
57 # $DEFAULT_USER_CUID , $UNKNOWN_USER_CUID, %BASE_USERS and %BASE_GROUPS
58 # could be initialised statically, but tests have been written that rely
59 # on being able to override the $Foswiki::cfg settings that are part of
60 # them. Since it's a low cost op to re-initialise them each time this
61 # singleton is built, we will contiue to do so (at least until those
62 # tests have been revisited)
63 $DEFAULT_USER_CUID = 'BaseUserMapping_666';
64 $UNKNOWN_USER_CUID = 'BaseUserMapping_999';
65 %BASE_USERS = (
66 BaseUserMapping_111 => {
67 login => 'ProjectContributor',
68 wikiname => 'ProjectContributor',
69 },
70 BaseUserMapping_222 => {
71 login => $Foswiki::cfg{Register}{RegistrationAgentWikiName}
72 || 'RegistrationAgent',
73 wikiname => $Foswiki::cfg{Register}{RegistrationAgentWikiName}
74 || 'RegistrationAgent',
75 },
76 BaseUserMapping_333 => {
77 login => $Foswiki::cfg{AdminUserLogin} || 'admin',
78 wikiname => $Foswiki::cfg{AdminUserWikiName} || 'AdminUser',
79 email => $Foswiki::cfg{WebMasterEmail} || 'email not set',
80 password => $Foswiki::cfg{Password},
81 },
82 $DEFAULT_USER_CUID => {
83 login => $Foswiki::cfg{DefaultUserLogin} || 'guest',
84 wikiname => $Foswiki::cfg{DefaultUserWikiName} || 'WikiGuest',
85 },
86 $UNKNOWN_USER_CUID => {
87 login => 'unknown',
88 wikiname => 'UnknownUser',
89 }
90 );
91 %BASE_GROUPS = (
92 $Foswiki::cfg{SuperAdminGroup} => [
93 'BaseUserMapping_333',
94
95# Registration agent was here so registration can still take
96# place on an otherwise locked down USERSWEB.
97# Jan2010: Sven removed it, otherwise anyone registering can add themselves as admin.
98#'BaseUserMapping_222'
99 ],
100 BaseGroup => [
101 'BaseUserMapping_333', $DEFAULT_USER_CUID,
102 $UNKNOWN_USER_CUID, 'BaseUserMapping_111',
103 'BaseUserMapping_222',
104 ],
105
106 # RegistrationGroup => ['BaseUserMapping_222']
107 );
108
109119µs my $this = $class->SUPER::new( $session, 'BaseUserMapping_' );
# spent 19µs making 1 call to Foswiki::UserMapping::new
110 $Foswiki::cfg{Register}{RegistrationAgentWikiName} ||= 'RegistrationAgent';
111
112 # set up our users
113 $this->{L2U} = {}; # login 2 cUID
114 $this->{U2L} = {}; # cUID 2 login
115 $this->{W2U} = {}; # wikiname 2 cUID
116 $this->{U2W} = {}; # cUID 2 wikiname
117 $this->{U2E} = {}; # cUID 2 email
118 $this->{L2P} = {}; # login 2 password
119
120 while ( my ( $k, $v ) = each %BASE_USERS ) {
121 $this->{U2L}->{$k} = $v->{login};
122 $this->{U2W}->{$k} = $v->{wikiname};
123 $this->{U2E}->{$k} = $v->{email} if defined $v->{email};
124
125 $this->{L2U}->{ $v->{login} } = $k;
126 $this->{L2P}->{ $v->{login} } = $v->{password}
127 if defined $v->{password};
128
129 $this->{W2U}->{ $v->{wikiname} } = $k;
130 }
131
132 %{ $this->{GROUPS} } = %BASE_GROUPS;
133
134 return $this;
135}
136
137=begin TML
138
139---++ ObjectMethod finish()
140Break circular references.
141
142=cut
143
144# Note to developers; please undef *all* fields in the object explicitly,
145# whether they are references or not. That way this method is "golden
146# documentation" of the live fields in the object.
147
# spent 107µs (94+13) within Foswiki::Users::BaseUserMapping::finish which was called: # once (94µs+13µs) by Foswiki::Users::finish at line 163 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm
sub finish {
148987µs my $this = shift;
149 undef $this->{U2L};
150 undef $this->{U2W};
151 undef $this->{L2P};
152 undef $this->{U2E};
153 undef $this->{L2U};
154 undef $this->{W2U};
155 undef $this->{GROUPS};
156113µs $this->SUPER::finish();
# spent 13µs making 1 call to Foswiki::UserMapping::finish
157}
158
159=begin TML
160
161---++ ObjectMethod loginTemplateName () -> templateFile
162
163allows UserMappings to come with customised login screens - that should preffereably only over-ride the UI function
164
165=cut
166
167sub loginTemplateName {
168 return 'login.sudo';
169}
170
171=begin TML
172
173---++ ObjectMethod handlesUser ( $cUID, $login, $wikiname) -> $boolean
174
175See baseclass for documentation.
176
177In the BaseUserMapping case, we know all
178the details of the users we specialise in.
179
180=cut
181
182
# spent 5.49ms within Foswiki::Users::BaseUserMapping::handlesUser which was called 515 times, avg 11µs/call: # 401 times (4.21ms+0s) by Foswiki::Users::TopicUserMapping::_cacheUser at line 1491 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users/TopicUserMapping.pm, avg 11µs/call # 114 times (1.28ms+0s) by Foswiki::Users::_getMapping at line 211 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm, avg 11µs/call
sub handlesUser {
18325736.28ms my ( $this, $cUID, $login, $wikiname ) = @_;
184
185 return 1 if ( defined($cUID) && defined( $this->{U2L}{$cUID} ) );
186 return 1 if ( defined($login) && defined( $this->{L2U}{$login} ) );
187 return 1 if ( defined($wikiname) && defined( $this->{W2U}{$wikiname} ) );
188
189 return 0;
190}
191
192=begin TML
193
194---++ ObjectMethod login2cUID ($login) -> $cUID
195
196Convert a login name to the corresponding canonical user name. The
197canonical name can be any string of 7-bit alphanumeric and underscore
198characters, and must correspond 1:1 to the login name.
199(undef on failure)
200
201=cut
202
203sub login2cUID {
204 my ( $this, $login ) = @_;
205
206 return $this->{L2U}{$login};
207
208 #alternative impl - slower, but more re-useable
209 #my @list = findUserByWikiName($this, $login);
210 #return shift @list;
211}
212
213=begin TML
214
215---++ ObjectMethod getLoginName ($cUID) -> login
216
217converts an internal cUID to that user's login
218(undef on failure)
219
220=cut
221
222sub getLoginName {
223 my ( $this, $user ) = @_;
224 return $this->{U2L}{$user};
225}
226
227=begin TML
228
229---++ ObjectMethod getWikiName ($cUID) -> wikiname
230
231Map a canonical user name to a wikiname
232
233=cut
234
235sub getWikiName {
236 my ( $this, $cUID ) = @_;
237 return $this->{U2W}->{$cUID} || getLoginName( $this, $cUID );
238}
239
240=begin TML
241
242---++ ObjectMethod userExists( $user ) -> $boolean
243
244Determine if the user already exists or not.
245
246=cut
247
248sub userExists {
249 my ( $this, $cUID ) = @_;
250 ASSERT($cUID) if DEBUG;
251 return 0 unless defined $cUID;
252 return $this->{U2L}{$cUID};
253}
254
255=begin TML
256
257---++ ObjectMethod eachUser () -> listIterator of cUIDs
258
259See baseclass for documentation.
260
261=cut
262
263sub eachUser {
264 my ($this) = @_;
265
266 my @list = keys( %{ $this->{U2W} } );
267 require Foswiki::ListIterator;
268 return new Foswiki::ListIterator( \@list );
269}
270
271=begin TML
272
273---++ ObjectMethod eachGroupMember ($group) -> listIterator of cUIDs
274
275See baseclass for documentation.
276
277The basemapper implementation assumes that there are no nested groups in the
278basemapper.
279
280=cut
281
282
# spent 132µs (70+62) within Foswiki::Users::BaseUserMapping::eachGroupMember which was called 3 times, avg 44µs/call: # 2 times (49µs+41µs) by Foswiki::Users::eachGroupMember at line 802 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm, avg 45µs/call # once (21µs+21µs) by Foswiki::UserMapping::isInGroup at line 401 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/UserMapping.pm
sub eachGroupMember {
2831568µs my $this = shift;
284 my $group = shift;
285
286 my $members = $this->{GROUPS}{$group};
287
288 #print STDERR "eachGroupMember($group): ".join(',', @{$members});
289
290 require Foswiki::ListIterator;
291362µs return new Foswiki::ListIterator($members);
# spent 62µs making 3 calls to Foswiki::ListIterator::new, avg 21µs/call
292}
293
294=begin TML
295
296---++ ObjectMethod isGroup ($name) -> boolean
297
298See baseclass for documentation.
299
300=cut
301
302
# spent 88.4ms within Foswiki::Users::BaseUserMapping::isGroup which was called 12225 times, avg 7µs/call: # 12164 times (87.9ms+0s) by Foswiki::Users::isGroup at line 821 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm, avg 7µs/call # 60 times (422µs+0s) by Foswiki::Users::BaseUserMapping::findUserByWikiName at line 404, avg 7µs/call # once (8µs+0s) by Foswiki::UserMapping::isInGroup at line 408 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/UserMapping.pm
sub isGroup {
30336675111ms my ( $this, $name ) = @_;
304 $name ||= "";
305
306 #TODO: what happens to the code if we implement this using an iterator too?
307 return ( $this->{GROUPS}->{$name} );
308}
309
310=begin TML
311
312---++ ObjectMethod eachGroup () -> ListIterator of groupnames
313
314See baseclass for documentation.
315
316=cut
317
318sub eachGroup {
319 my ($this) = @_;
320 my @groups = keys( %{ $this->{GROUPS} } );
321
322 require Foswiki::ListIterator;
323 return new Foswiki::ListIterator( \@groups );
324}
325
326=begin TML
327
328---++ ObjectMethod eachMembership ($cUID) -> ListIterator of groups this user is in
329
330See baseclass for documentation.
331
332=cut
333
334sub eachMembership {
335 my ( $this, $cUID ) = @_;
336
337 my $it = $this->eachGroup();
338 $it->{filter} = sub {
339 $this->isInGroup( $cUID, $_[0] );
340 };
341 return $it;
342}
343
344=begin TML
345
346---++ ObjectMethod groupAllowsChange($group) -> boolean
347
348returns 0 if the group is 'owned by the BaseMapper and it wants to veto adding to that group
349
350=cut
351
352sub groupAllowsChange {
353 my $this = shift;
354 my $group = shift;
355 ASSERT( defined $group ) if DEBUG;
356
357 return 0
358 if ( ( $group eq 'BaseGroup' )
359 or ( $group eq 'RegistrationGroup' ) );
360 return 1;
361}
362
363=begin TML
364
365---++ ObjectMethod isAdmin( $cUID ) -> $boolean
366
367True if the user is an admin
368 * is a member of the $Foswiki::cfg{SuperAdminGroup}
369
370=cut
371
372
# spent 234µs (26+207) within Foswiki::Users::BaseUserMapping::isAdmin which was called: # once (26µs+207µs) by Foswiki::Users::isAdmin at line 608 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm
sub isAdmin {
373227µs my ( $this, $cUID ) = @_;
3741207µs return $this->isInGroup( $cUID, $Foswiki::cfg{SuperAdminGroup} );
# spent 207µs making 1 call to Foswiki::UserMapping::isInGroup
375}
376
377=begin TML
378
379---++ ObjectMethod getEmails($name) -> @emailAddress
380
381If $name is a cUID, return their email addresses. If it is a group,
382return the addresses of everyone in the group.
383
384=cut
385
386sub getEmails {
387 my ( $this, $user ) = @_;
388
389 return $this->{U2E}{$user} || ();
390}
391
392=begin TML
393
394---++ ObjectMethod findUserByWikiName ($wikiname) -> list of cUIDs associated with that wikiname
395
396See baseclass for documentation.
397
398=cut
399
400
# spent 1.50ms (1.08+422µs) within Foswiki::Users::BaseUserMapping::findUserByWikiName which was called 60 times, avg 25µs/call: # 60 times (1.08ms+422µs) by Foswiki::Users::findUserByWikiName at line 517 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Users.pm, avg 25µs/call
sub findUserByWikiName {
4013001.03ms my ( $this, $wn ) = @_;
402 my @users = ();
403
40460422µs if ( $this->isGroup($wn) ) {
# spent 422µs making 60 calls to Foswiki::Users::BaseUserMapping::isGroup, avg 7µs/call
405 push( @users, $wn );
406 }
407 else {
408
409 # Add additional mappings defined in WikiUsers
410 if ( $this->{W2U}->{$wn} ) {
411 push( @users, $this->{W2U}->{$wn} );
412 }
413 elsif ( $this->{L2U}->{$wn} ) {
414
415 # The wikiname is also a login name for the purposes of this
416 # mapping. We have to do this because Foswiki defines access controls
417 # in terms of mapped users, and if a wikiname is *missing* from the
418 # mapping there is "no such user".
419 push( @users, $this->{L2U}->{$wn} );
420 }
421 }
422 return \@users;
423}
424
425=begin TML
426
427---++ ObjectMethod checkPassword( $login, $passwordU ) -> $boolean
428
429Finds if the password is valid for the given user.
430
431Returns 1 on success, undef on failure.
432
433=cut
434
435sub checkPassword {
436 my ( $this, $login, $pass ) = @_;
437
438 my $hash = $this->{L2P}->{$login};
439 if ( $hash && crypt( $pass, $hash ) eq $hash ) {
440 return 1; # yay, you've passed
441 }
442
443 # be a little more helpful to the admin
444 if ( $login eq $Foswiki::cfg{AdminUserLogin} && !$hash ) {
445 $this->{error} =
446 'To login as ' . $login . ', you must set {Password} in configure';
447 }
448 return 0;
449}
450
451=begin TML
452
453---++ ObjectMethod setPassword( $cUID, $newPassU, $oldPassU ) -> $boolean
454
455If the $oldPassU matches matches the user's password, then it will
456replace it with $newPassU.
457
458If $oldPassU is not correct and not 1, will return 0.
459
460If $oldPassU is 1, will force the change irrespective of
461the existing password, adding the user if necessary.
462
463Otherwise returns 1 on success, undef on failure.
464
465=cut
466
467sub setPassword {
468 my ( $this, $cUID, $newPassU, $oldPassU ) = @_;
469 throw Error::Simple(
470 'cannot change user passwords using Foswiki::BaseUserMapping');
471}
472
473=begin TML
474
475---++ ObjectMethod passwordError( ) -> $string
476
477returns a string indicating the error that happened in the password handlers
478TODO: these delayed error's should be replaced with Exceptions.
479
480returns undef if no error
481
482=cut
483
484sub passwordError {
485 my $this = shift;
486
487 return $this->{error};
488}
489
49017µs1;
491__END__