← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:14 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Users.pm
StatementsExecuted 4794 statements in 11.5ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1115.80ms8.55msFoswiki::Users::::newFoswiki::Users::new
1115.16ms9.30msFoswiki::Users::::BEGIN@64Foswiki::Users::BEGIN@64
1066111.59ms1.59msFoswiki::Users::::mapLogin2cUIDFoswiki::Users::mapLogin2cUID
353551.07ms1.16msFoswiki::Users::::isAdminFoswiki::Users::isAdmin
111464µs938µsFoswiki::Users::::BEGIN@63Foswiki::Users::BEGIN@63
6211364µs649µsFoswiki::Users::::isGroupFoswiki::Users::isGroup
4844150µs210µsFoswiki::Users::::getLoginNameFoswiki::Users::getLoginName
1855101µs136µsFoswiki::Users::::getWikiNameFoswiki::Users::getWikiName
84189µs32.0msFoswiki::Users::::_getMappingFoswiki::Users::_getMapping
64471µs32.1msFoswiki::Users::::getCanonicalUserIDFoswiki::Users::getCanonicalUserID
11153µs1.35msFoswiki::Users::::finishFoswiki::Users::finish
52234µs89µsFoswiki::Users::::webDotWikiNameFoswiki::Users::webDotWikiName
101127µs27µsFoswiki::Users::::getLoginManagerFoswiki::Users::getLoginManager
32125µs34µsFoswiki::Users::::getCGISessionFoswiki::Users::getCGISession
11115µs3.11msFoswiki::Users::::initialiseUserFoswiki::Users::initialiseUser
11114µs168µsFoswiki::Users::::loadSessionFoswiki::Users::loadSession
11113µs26µsFoswiki::Users::::BEGIN@59Foswiki::Users::BEGIN@59
11113µs34µsFoswiki::Users::::BEGIN@313Foswiki::Users::BEGIN@313
11111µs14µsFoswiki::Users::::BEGIN@408Foswiki::Users::BEGIN@408
11110µs12µsFoswiki::Users::::BEGIN@406Foswiki::Users::BEGIN@406
1119µs37µsFoswiki::Users::::BEGIN@61Foswiki::Users::BEGIN@61
1119µs13µsFoswiki::Users::::BEGIN@60Foswiki::Users::BEGIN@60
1118µs8µsFoswiki::Users::::supportsRegistrationFoswiki::Users::supportsRegistration
1115µs5µsFoswiki::Users::::BEGIN@69Foswiki::Users::BEGIN@69
0000s0sFoswiki::Users::::addUserFoswiki::Users::addUser
0000s0sFoswiki::Users::::addUserToGroupFoswiki::Users::addUserToGroup
0000s0sFoswiki::Users::::checkPasswordFoswiki::Users::checkPassword
0000s0sFoswiki::Users::::eachGroupFoswiki::Users::eachGroup
0000s0sFoswiki::Users::::eachGroupMemberFoswiki::Users::eachGroupMember
0000s0sFoswiki::Users::::eachMembershipFoswiki::Users::eachMembership
0000s0sFoswiki::Users::::eachUserFoswiki::Users::eachUser
0000s0sFoswiki::Users::::findUserByEmailFoswiki::Users::findUserByEmail
0000s0sFoswiki::Users::::findUserByWikiNameFoswiki::Users::findUserByWikiName
0000s0sFoswiki::Users::::getEmailsFoswiki::Users::getEmails
0000s0sFoswiki::Users::::groupAllowsChangeFoswiki::Users::groupAllowsChange
0000s0sFoswiki::Users::::groupAllowsViewFoswiki::Users::groupAllowsView
0000s0sFoswiki::Users::::isInGroupFoswiki::Users::isInGroup
0000s0sFoswiki::Users::::isInUserListFoswiki::Users::isInUserList
0000s0sFoswiki::Users::::loginTemplateNameFoswiki::Users::loginTemplateName
0000s0sFoswiki::Users::::passwordErrorFoswiki::Users::passwordError
0000s0sFoswiki::Users::::randomPasswordFoswiki::Users::randomPassword
0000s0sFoswiki::Users::::removeUserFoswiki::Users::removeUser
0000s0sFoswiki::Users::::removeUserFromGroupFoswiki::Users::removeUserFromGroup
0000s0sFoswiki::Users::::setEmailsFoswiki::Users::setEmails
0000s0sFoswiki::Users::::setPasswordFoswiki::Users::setPassword
0000s0sFoswiki::Users::::userExistsFoswiki::Users::userExists
0000s0sFoswiki::Users::::validateRegistrationFieldFoswiki::Users::validateRegistrationField
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
6This package provides services for the lookup and manipulation of login and
7wiki names of users, and their authentication.
8
9It is a Facade that presents a common interface to the User Mapping
10and Password modules. The rest of the core should *only* use the methods
11of this package, and should *never* call the mapping or password managers
12directly.
13
14Foswiki uses the concept of a _login name_ which is used to authenticate a
15user. A login name maps to a _wiki name_ that is used to identify the user
16for display. Each login name is unique to a single user, though several
17login names may map to the same wiki name.
18
19Using this module (and the associated plug-in user mapper) Foswiki supports
20the concept of _groups_. Groups are sets of login names that are treated
21equally for the purposes of access control. Group names do not have to be
22wiki names, though it is helpful for display if they are.
23
24Internally in the code Foswiki uses something referred to as a _canonical user
25id_ or just _user id_. The user id is also used externally to uniquely identify
26the user when (for example) recording topic histories. The user id is *usually*
27just the login name, but it doesn't need to be. It just has to be a unique
287-bit alphanumeric and underscore string that can be mapped to/from login
29and wiki names by the user mapper.
30
31The canonical user id should *never* be seen by a user. On the other hand,
32core code should never use anything *but* a canonical user id to refer
33to a user.
34
35*Terminology*
36 * A *login name* is the name used to log in to Foswiki. Each login name is
37 assumed to be unique to a human. The Password module is responsible for
38 authenticating and manipulating login names.
39 * A *canonical user id* is an internal Foswiki representation of a user. Each
40 canonical user id maps 1:1 to a login name.
41 * A *wikiname* is how a user is displayed. Many user ids may map to a
42 single wikiname. The user mapping module is responsible for mapping
43 the user id to a wikiname.
44 * A *group id* represents a group of users and other groups.
45 The user mapping module is responsible for mapping from a group id to
46 a list of canonical user ids for the users in that group.
47 * An *email* is an email address asscoiated with a *login name*. A single
48 login name may have many emails.
49
50*NOTE:*
51 * wherever the code references $cUID, its a canonical_id
52 * wherever the code references $group, its a group_name
53 * $name may be a group or a cUID
54
55=cut
56
57package Foswiki::Users;
58
59227µs240µs
# spent 26µs (13+13) within Foswiki::Users::BEGIN@59 which was called: # once (13µs+13µs) by Foswiki::BEGIN@647 at line 59
use strict;
# spent 26µs making 1 call to Foswiki::Users::BEGIN@59 # spent 13µs making 1 call to strict::import
60223µs218µs
# spent 13µs (9+5) within Foswiki::Users::BEGIN@60 which was called: # once (9µs+5µs) by Foswiki::BEGIN@647 at line 60
use warnings;
# spent 13µs making 1 call to Foswiki::Users::BEGIN@60 # spent 4µs making 1 call to warnings::import
61228µs266µs
# spent 37µs (9+28) within Foswiki::Users::BEGIN@61 which was called: # once (9µs+28µs) by Foswiki::BEGIN@647 at line 61
use Assert;
# spent 37µs making 1 call to Foswiki::Users::BEGIN@61 # spent 28µs making 1 call to Exporter::import
62
63295µs1938µs
# spent 938µs (464+474) within Foswiki::Users::BEGIN@63 which was called: # once (464µs+474µs) by Foswiki::BEGIN@647 at line 63
use Foswiki::AggregateIterator ();
# spent 938µs making 1 call to Foswiki::Users::BEGIN@63
642130µs19.30ms
# spent 9.30ms (5.16+4.13) within Foswiki::Users::BEGIN@64 which was called: # once (5.16ms+4.13ms) by Foswiki::BEGIN@647 at line 64
use Foswiki::LoginManager ();
# spent 9.30ms making 1 call to Foswiki::Users::BEGIN@64
65
66#use Monitor;
67#Monitor::MonitorMethod('Foswiki::Users');
68
69
# spent 5µs within Foswiki::Users::BEGIN@69 which was called: # once (5µs+0s) by Foswiki::BEGIN@647 at line 74
BEGIN {
7015µs if ( $Foswiki::cfg{UseLocale} ) {
71 require locale;
72 import locale();
73 }
741663µs15µs}
# spent 5µs making 1 call to Foswiki::Users::BEGIN@69
75
76=begin TML
77
78---++ ClassMethod new ($session)
79Construct the user management object that is the facade to the BaseUserMapping
80and the user mapping chosen in the configuration.
81
82=cut
83
84
# spent 8.55ms (5.80+2.74) within Foswiki::Users::new which was called: # once (5.80ms+2.74ms) by Foswiki::new at line 2126 of /var/www/foswikidev/core/lib/Foswiki.pm
sub new {
8511µs my ( $class, $session ) = @_;
8617µs my $this = bless( { session => $session }, $class );
87
88 # making basemapping
8912µs my $implBaseUserMappingManager = $Foswiki::cfg{BaseUserMappingManager}
90 || 'Foswiki::Users::BaseUserMapping';
91121µs eval "require $implBaseUserMappingManager";
# spent 2µs executing statements in string eval
921900ns die $@ if $@;
9316µs174µs $this->{basemapping} = $implBaseUserMappingManager->new($session);
# spent 74µs making 1 call to Foswiki::Users::BaseUserMapping::new
94
9512µs my $implUserMappingManager = $Foswiki::cfg{UserMappingManager};
9611µs $implUserMappingManager = 'Foswiki::Users::TopicUserMapping'
97 if ( $implUserMappingManager eq 'none' );
98
991800ns if ( $implUserMappingManager eq 'Foswiki::Users::BaseUserMapping' ) {
100 $this->{mapping} = $this->{basemapping}; #TODO: probly make undef..
101 }
102 else {
103120µs eval "require $implUserMappingManager";
# spent 81µs executing statements in string eval
1041600ns die $@ if $@;
105112µs1716µs $this->{mapping} = $implUserMappingManager->new($session);
# spent 716µs making 1 call to Foswiki::Users::TopicUserMapping::new
106 }
107
10814µs1880µs $this->{loginManager} = Foswiki::LoginManager::makeLoginManager($session);
# spent 880µs making 1 call to Foswiki::LoginManager::makeLoginManager
109
110 # caches - not only used for speedup, but also for authenticated but
111 # unregistered users
112 # SMELL: this is basically a user object, something we had previously
113 # but dropped for efficiency reasons
11411µs $this->{cUID2WikiName} = {};
11511µs $this->{cUID2Login} = {};
1161800ns $this->{isAdmin} = {};
117
118 # the UI for rego supported/not is different from rego temporarily
119 # turned off
12013µs18µs if ( $this->supportsRegistration() ) {
# spent 8µs making 1 call to Foswiki::Users::supportsRegistration
12111µs13µs $session->enterContext('registration_supported');
# spent 3µs making 1 call to Foswiki::enterContext
12212µs12µs $session->enterContext('registration_enabled')
# spent 2µs making 1 call to Foswiki::enterContext
123 if $Foswiki::cfg{Register}{EnableNewUserRegistration};
124 }
125
12614µs return $this;
127}
128
129=begin TML
130
131---++ ObjectMethod loadSession()
132
133Setup the cgi session, from a cookie or the url. this may return
134the login, but even if it does, plugins will get the chance to
135override (in Foswiki.pm)
136
137=cut
138
139
# spent 168µs (14+153) within Foswiki::Users::loadSession which was called: # once (14µs+153µs) by Foswiki::new at line 2161 of /var/www/foswikidev/core/lib/Foswiki.pm
sub loadSession {
14011µs my ( $this, $defaultUser ) = @_;
141
142 # $this is passed in because it will be used to password check
143 # a command-line login. The {remoteUser} in the session will be
144 # whatever was passed in to the new Foswiki() call.
14517µs1153µs my $remoteUser = $this->{loginManager}->loadSession( $defaultUser, $this );
# spent 153µs making 1 call to Foswiki::LoginManager::loadSession
146
14714µs return $remoteUser;
148}
149
150=begin TML
151
152---++ ObjectMethod finish()
153Break circular references.
154
155=cut
156
157# Note to developers; please undef *all* fields in the object explicitly,
158# whether they are references or not. That way this method is "golden
159# documentation" of the live fields in the object.
160
# spent 1.35ms (53µs+1.30) within Foswiki::Users::finish which was called: # once (53µs+1.30ms) by Foswiki::finish at line 2488 of /var/www/foswikidev/core/lib/Foswiki.pm
sub finish {
1611500ns my $this = shift;
162
163111µs1146µs $this->{loginManager}->finish() if $this->{loginManager};
# spent 146µs making 1 call to Foswiki::LoginManager::finish
16416µs146µs $this->{basemapping}->finish() if $this->{basemapping};
# spent 46µs making 1 call to Foswiki::Users::BaseUserMapping::finish
165
16616µs11.10ms $this->{mapping}->finish()
# spent 1.10ms making 1 call to Foswiki::Users::TopicUserMapping::finish
167 if $this->{mapping}
168 && $this->{mapping} ne $this->{basemapping};
169
17016µs undef $this->{loginManager};
17116µs undef $this->{basemapping};
17215µs undef $this->{mapping};
1731500ns undef $this->{session};
17412µs undef $this->{cUID2WikiName};
1751700ns undef $this->{cUID2Login};
1761900ns undef $this->{wikiName2cUID};
17711µs undef $this->{login2cUID};
17814µs undef $this->{isAdmin};
179
180}
181
182=begin TML
183
184---++ ObjectMethod loginTemplateName () -> templateFile
185
186allows UserMappings to come with customised login screens - that should preffereably only over-ride the UI function
187
188=cut
189
190sub loginTemplateName {
191 my $this = shift;
192
193 #use login.sudo.tmpl for admin logins
194 return $this->{basemapping}->loginTemplateName()
195 if ( $this->{session}->inContext('sudo_login') );
196 return $this->{mapping}->loginTemplateName() || 'login';
197}
198
199# ($cUID, $login, $wikiname, $noFallBack) -> usermapping object
200
# spent 32.0ms (89µs+31.9) within Foswiki::Users::_getMapping which was called 8 times, avg 4.00ms/call: # 3 times (57µs+31.9ms) by Foswiki::Users::getCanonicalUserID at line 478, avg 10.7ms/call # 2 times (14µs+8µs) by Foswiki::Users::getWikiName at line 715, avg 11µs/call # 2 times (12µs+6µs) by Foswiki::Users::getLoginName at line 683, avg 9µs/call # once (6µs+2µs) by Foswiki::Users::isAdmin at line 618
sub _getMapping {
20186µs my ( $this, $cUID, $login, $wikiname, $noFallBack ) = @_;
202
20382µs $login = '' unless defined $login;
20483µs $wikiname = '' unless defined $wikiname;
205
206831µs $wikiname =~ s/^($Foswiki::cfg{UsersWebName}|%USERSWEB%|%MAINWEB%)\.//;
207
208 # The base user mapper users must always override those defined in
209 # custom mappings, even though that makes it impossible to maintain 100%
210 # compatibility with earlier releases (guest user edits will get saved as
211 # edits by $DEFAULT_USER_CUID).
212829µs826µs return $this->{basemapping}
# spent 26µs making 8 calls to Foswiki::Users::BaseUserMapping::handlesUser, avg 3µs/call
213 if ( $this->{basemapping}->handlesUser( $cUID, $login, $wikiname ) );
214
215315µs331.9ms return $this->{mapping}
# spent 31.9ms making 3 calls to Foswiki::Users::TopicUserMapping::handlesUser, avg 10.6ms/call
216 if ( $this->{mapping}->handlesUser( $cUID, $login, $wikiname ) );
217
218 # The base mapping and the selected mapping claim not to know about
219 # this user. Use the base mapping unless the caller has explicitly
220 # requested otherwise.
221 return $this->{basemapping} unless ($noFallBack);
222
223 return;
224}
225
226=begin TML
227
228---++ ObjectMethod supportsRegistration () -> boolean
229
230#return 1 if the main UserMapper supports registration (ie can create new users)
231
232=cut
233
234
# spent 8µs (8+800ns) within Foswiki::Users::supportsRegistration which was called: # once (8µs+800ns) by Foswiki::Users::new at line 120
sub supportsRegistration {
2351700ns my ($this) = @_;
23614µs1800ns return $this->{mapping}->supportsRegistration();
237}
238
239=begin TML
240
241---++ ObjectMethod validateRegistrationField ( $field, $value ) -> text
242
243Return the registration formfield sanitized by the mapper, or oops thrown to block the registration.
244
245=cut
246
247sub validateRegistrationField {
248 my ($this) = shift;
249 return $this->{mapping}->validateRegistrationField(@_);
250}
251
252=begin TML
253
254---++ ObjectMethod initialiseUser ($login) -> $cUID
255
256Given a login (which must have been authenticated) determine the cUID that
257corresponds to that user. This method is used from Foswiki.pm to map the
258$REMOTE_USER to a cUID.
259
260=cut
261
262
# spent 3.11ms (15µs+3.09) within Foswiki::Users::initialiseUser which was called: # once (15µs+3.09ms) by Foswiki::new at line 2227 of /var/www/foswikidev/core/lib/Foswiki.pm
sub initialiseUser {
2631900ns my ( $this, $login ) = @_;
264
265 # For compatibility with older ways of building login managers,
266 # plugins can provide an alternate login name.
26714µs13.06ms my $plogin = $this->{session}->{plugins}->load();
# spent 3.06ms making 1 call to Foswiki::Plugins::load
268
269 #Monitor::MARK("Plugins loaded");
270
2711700ns $login = $plogin if $plogin;
272
2731200ns my $cUID;
27411µs if ( defined($login) && $login ne '' ) {
275
276 # In the case of a user mapper that accepts any identifier as
277 # a cUID,
27812µs127µs $cUID = $this->getCanonicalUserID($login);
# spent 27µs making 1 call to Foswiki::Users::getCanonicalUserID
279
280 # see BugsItem4771 - it seems that authenticated, but unmapped
281 # users have rights too
2821300ns if ( !defined($cUID) ) {
283
284 # There is no known canonical user ID for this login name.
285 # Generate a cUID for the login, and add it anyway. There is
286 # a risk that the generated cUID will overlap a cUID generated
287 # by a custom mapper, but since (1) the user has to be
288 # authenticated to get here and (2) the custom user mapper
289 # is specific to the login process used, that risk should be
290 # small (unless the author of the custom mapper screws up)
291 $cUID = mapLogin2cUID($login);
292
293 $this->{cUID2Login}->{$cUID} = $login;
294 $this->{cUID2WikiName}->{$cUID} = $login;
295
296 # needs to be WikiName safe
297 $this->{cUID2WikiName}->{$cUID} =~ s/$Foswiki::cfg{NameFilter}//g;
298 $this->{cUID2WikiName}->{$cUID} =~ s/\.//g;
299
300 $this->{login2cUID}->{$login} = $cUID;
301 $this->{wikiName2cUID}->{ $this->{cUID2WikiName}->{$cUID} } = $cUID;
302 }
303 }
304
305 # if we get here without a login id, we are a guest. Get the guest
306 # cUID.
3071200ns $cUID ||= $this->getCanonicalUserID( $Foswiki::cfg{DefaultUserLogin} );
308
30913µs return $cUID;
310}
311
312# global used by test harness to give predictable results
3132242µs256µs
# spent 34µs (13+22) within Foswiki::Users::BEGIN@313 which was called: # once (13µs+22µs) by Foswiki::BEGIN@647 at line 313
use vars qw( $password );
# spent 34µs making 1 call to Foswiki::Users::BEGIN@313 # spent 22µs making 1 call to vars::import
314
315=begin TML
316
317---++ randomPassword()
318Static function that returns a random password. This function is not used
319in this module; it is provided as a service for other modules, such as
320custom mappers and registration modules.
321
322=cut
323
324sub randomPassword {
325
326 my $pwlen =
327 ( $Foswiki::cfg{MinPasswordLength} > 8 )
328 ? $Foswiki::cfg{MinPasswordLength}
329 : 8;
330 my @chars = ( 'a' .. 'z', 'A' .. 'Z', 0 .. 9, '_', '.', '/' );
331 my $newpw;
332
333 foreach ( 1 .. $pwlen ) {
334 $newpw .= $chars[ rand @chars ];
335 }
336 return $newpw;
337
338}
339
340=begin TML
341
342---++ ObjectMethod addUser($login, $wikiname, $password, $emails) -> $cUID
343
344 * =$login= - user login name. If =undef=, =$wikiname= will be used as
345 the login name.
346 * =$wikiname= - user wikiname. If =undef=, the user mapper will be asked
347 to provide it.
348 * =$password= - password. If undef, a password will be generated.
349
350Add a new Foswiki user identity, returning the canonical user id for the new
351user. Used ONLY for user registration.
352
353The user is added to the password system (if there is one, and if it accepts
354changes). If the user already exists in the password system, then the password
355is checked and an exception thrown if it doesn't match. If there is no
356existing user, and no password is given, a random password is generated.
357
358$login can be undef; $wikiname must always have a value.
359
360The return value is the canonical user id that is used
361by Foswiki to identify the user.
362
363=cut
364
365sub addUser {
366 my ( $this, $login, $wikiname, $password, $emails ) = @_;
367 my $removeOnFail = 0;
368
369 ASSERT( $login || $wikiname ) if DEBUG; # must have at least one
370
371 # create a new user and get the canonical user ID from the user mapping
372 # manager.
373 my $cUID =
374 $this->{mapping}->addUser( $login, $wikiname, $password, $emails );
375
376 # update the cached values
377 $this->{cUID2Login}->{$cUID} = $login;
378 $this->{cUID2WikiName}->{$cUID} = $wikiname;
379
380 $this->{login2cUID}->{$login} = $cUID;
381 $this->{wikiName2cUID}->{$wikiname} = $cUID;
382
383 return $cUID;
384}
385
386=begin TML
387
388---++ StaticMethod mapLogin2cUID( $login ) -> $cUID
389
390This function maps an arbitrary string into a valid cUID. The transformation
391is reversible, but the function is not idempotent (a cUID passed to this
392function will NOT be returned unchanged). The generated cUID will be unique
393for the given login name.
394
395This static function is designed to be called from custom user mappers that
396support 1:1 login-to-cUID mappings.
397
398=cut
399
400
# spent 1.59ms within Foswiki::Users::mapLogin2cUID which was called 1066 times, avg 1µs/call: # 1066 times (1.59ms+0s) by Foswiki::Users::TopicUserMapping::login2cUID at line 180 of /var/www/foswikidev/core/lib/Foswiki/Users/TopicUserMapping.pm, avg 1µs/call
sub mapLogin2cUID {
4011066222µs my $cUID = shift;
402
403 ASSERT( defined($cUID) ) if DEBUG;
404
405 # use bytes to ignore character encoding
406254µs215µs
# spent 12µs (10+2) within Foswiki::Users::BEGIN@406 which was called: # once (10µs+2µs) by Foswiki::BEGIN@647 at line 406
use bytes;
# spent 12µs making 1 call to Foswiki::Users::BEGIN@406 # spent 2µs making 1 call to bytes::import
4071066484µs $cUID =~ s/([^a-zA-Z0-9])/'_'.sprintf('%02x', ord($1))/ge;
40821.61ms217µs
# spent 14µs (11+3) within Foswiki::Users::BEGIN@408 which was called: # once (11µs+3µs) by Foswiki::BEGIN@647 at line 408
no bytes;
# spent 14µs making 1 call to Foswiki::Users::BEGIN@408 # spent 3µs making 1 call to bytes::unimport
40910665.48ms return $cUID;
410}
411
412=begin TML
413
414---++ ObjectMethod getCGISession()
415Get the currect CGI session object
416
417=cut
418
419
# spent 34µs (25+10) within Foswiki::Users::getCGISession which was called 3 times, avg 11µs/call: # 2 times (19µs+7µs) by Foswiki::getCGISession at line 1348 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 13µs/call # once (6µs+2µs) by Foswiki::writeCompletePage at line 675 of /var/www/foswikidev/core/lib/Foswiki.pm
sub getCGISession {
42032µs my $this = shift;
421324µs310µs return $this->{loginManager}->getCGISession();
# spent 10µs making 3 calls to Foswiki::LoginManager::getCGISession, avg 3µs/call
422}
423
424=begin TML
425
426---++ ObjectMethod getLoginManager() -> $loginManager
427
428Get the Foswiki::LoginManager object associated with this session, if there is
429one. May return undef.
430
431=cut
432
433
# spent 27µs within Foswiki::Users::getLoginManager which was called 10 times, avg 3µs/call: # 10 times (27µs+0s) by Foswiki::getLoginManager at line 1361 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 3µs/call
sub getLoginManager {
434104µs my $this = shift;
4351041µs return $this->{loginManager};
436}
437
438=begin TML
439
440---++ ObjectMethod getCanonicalUserID( $identifier ) -> $cUID
441
442Works out the Foswiki canonical user identifier for the user who either
443(1) logs in with the login name $identifier or (2) has the wikiname
444$identifier.
445
446The canonical user ID is an alphanumeric string that is unique
447to the login name, and can be mapped back to a login name and the
448corresponding wiki name using the methods of this class.
449
450Note that if the login name to wiki name mapping is not 1:1, this
451method will map a wikiname to one of the login names that corresponds
452to the wiki name, but there is no guarantee which one.
453
454Returns undef if the user does not exist.
455
456=cut
457
458# This function was previously known as forceCUID. It differs from that
459# implementation in that it does *not* accept a CUID as parameter, which
460# if why it has been renamed.
461
# spent 32.1ms (71µs+32.0) within Foswiki::Users::getCanonicalUserID which was called 6 times, avg 5.35ms/call: # 3 times (32µs+32.0ms) by Foswiki::Render::renderRevisionInfo at line 808 of /var/www/foswikidev/core/lib/Foswiki/Render.pm, avg 10.7ms/call # once (23µs+38µs) by Foswiki::LoginManager::userLoggedIn at line 804 of /var/www/foswikidev/core/lib/Foswiki/LoginManager.pm # once (12µs+15µs) by Foswiki::Users::initialiseUser at line 278 # once (4µs+0s) by Foswiki::Func::getCanonicalUserID at line 967 of /var/www/foswikidev/core/lib/Foswiki/Func.pm
sub getCanonicalUserID {
46265µs my ( $this, $identifier ) = @_;
46361µs my $cUID;
464
465 ASSERT( defined $identifier ) if DEBUG;
466
467 # Someone we already know?
468
469611µs if ( defined( $this->{login2cUID}->{$identifier} ) ) {
470 $cUID = $this->{login2cUID}->{$identifier};
471 }
472 elsif ( defined( $this->{wikiName2cUID}->{$identifier} ) ) {
473 $cUID = $this->{wikiName2cUID}->{$identifier};
474 }
475 else {
476
477 # See if a mapping recognises the identifier as a login name
47838µs332.0ms my $mapping = $this->_getMapping( undef, $identifier, undef, 1 );
# spent 32.0ms making 3 calls to Foswiki::Users::_getMapping, avg 10.7ms/call
47932µs if ($mapping) {
480327µs625µs if ( $mapping->can('login2cUID') ) {
# spent 16µs making 1 call to Foswiki::Users::TopicUserMapping::login2cUID # spent 5µs making 3 calls to UNIVERSAL::can, avg 2µs/call # spent 4µs making 2 calls to Foswiki::Users::BaseUserMapping::login2cUID, avg 2µs/call
481 $cUID = $mapping->login2cUID($identifier);
482 }
483 elsif ( $mapping->can('getCanonicalUserID') ) {
484
485 # Old name of login2cUID. Name changed to avoid confusion
486 # with Foswiki::Users::getCanonicalUserID. See
487 # Codev.UserMapperChangesBetween420And421 for more.
488 $cUID = $mapping->getCanonicalUserID($identifier);
489 }
490 else {
491 die(
492"Broken user mapping $mapping; does not implement login2cUID"
493 );
494 }
495 }
496
49731µs unless ($cUID) {
498
499 # Finally see if it's a valid user wikiname
500
501 # Strip users web id (legacy, probably specific to
502 # TopicUserMappingContrib but may be used by other mappers
503 # that support user topics)
504 my ( $dummy, $nid ) =
505 $this->{session}->normalizeWebTopicName( '', $identifier );
506 $identifier = $nid if ( $dummy eq $Foswiki::cfg{UsersWebName} );
507
508 my $found = $this->findUserByWikiName($identifier);
509 $cUID = $found->[0] if ( $found && scalar(@$found) );
510 }
511 }
512620µs return $cUID;
513}
514
515=begin TML
516
517---++ ObjectMethod findUserByWikiName( $wn ) -> \@users
518 * =$wn= - wikiname to look up
519Return a list of canonical user names for the users that have this wikiname.
520Since a single wikiname might be used by multiple login ids, we need a list.
521
522If $wn is the name of a group, the group will *not* be expanded.
523
524=cut
525
526sub findUserByWikiName {
527 my ( $this, $wn ) = @_;
528 ASSERT($wn) if DEBUG;
529
530 # Trim the (pointless) userweb, if present
531 $wn =~ s/^($Foswiki::cfg{UsersWebName}|%USERSWEB%|%MAINWEB%)\.//;
532 my $mapping = $this->_getMapping( undef, undef, $wn );
533
534 #my $mapping = $this->_getMapping( $wn, $wn, $wn ); # why not?
535 return $mapping->findUserByWikiName($wn);
536}
537
538=begin TML
539
540---++ ObjectMethod findUserByEmail( $email ) -> \@users
541 * =$email= - email address to look up
542Return a list of canonical user names for the users that have this email
543registered with the user mapping managers.
544
545=cut
546
547sub findUserByEmail {
548 my ( $this, $email ) = @_;
549 ASSERT($email) if DEBUG;
550
551 my $users = $this->{mapping}->findUserByEmail($email);
552 push @{$users}, @{ $this->{basemapping}->findUserByEmail($email) };
553
554 return $users;
555}
556
557=begin TML
558
559---++ ObjectMethod getEmails($name) -> @emailAddress
560
561If $name is a cUID, return their email addresses. If it is a group,
562return the addresses of everyone in the group.
563
564The password manager and user mapping manager are both consulted for emails
565for each user (where they are actually found is implementation defined).
566
567Duplicates are removed from the list.
568
569=cut
570
571sub getEmails {
572 my ( $this, $name ) = @_;
573
574 return () unless ($name);
575 if ( $this->{mapping}->isGroup($name) ) {
576 return $this->{mapping}->getEmails($name);
577 }
578
579 return $this->_getMapping($name)->getEmails($name);
580}
581
582=begin TML
583
584---++ ObjectMethod setEmails($cUID, @emails)
585
586Set the email address(es) for the given user.
587The password manager is tried first, and if it doesn't want to know the
588user mapping manager is tried.
589
590=cut
591
592sub setEmails {
593 my $this = shift;
594 my $cUID = shift;
595 my @emails = @_;
596 return $this->_getMapping($cUID)->setEmails( $cUID, @emails );
597}
598
599=begin TML
600
601---++ ObjectMethod isAdmin( $cUID ) -> $boolean
602
603True if the user is an admin
604 * is $Foswiki::cfg{SuperAdminGroup}
605 * is a member of the $Foswiki::cfg{SuperAdminGroup}
606 * Foswiki is bootstrapping a new configuration
607
608=cut
609
610
# spent 1.16ms (1.07+92µs) within Foswiki::Users::isAdmin which was called 353 times, avg 3µs/call: # 252 times (571µs+0s) by Foswiki::Access::TopicACLAccess::haveAccess at line 91 of /var/www/foswikidev/core/lib/Foswiki/Access/TopicACLAccess.pm, avg 2µs/call # 80 times (432µs+0s) by Foswiki::Store::Interfaces::QueryAlgorithm::getWebIterator at line 206 of /var/www/foswikidev/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm, avg 5µs/call # 19 times (47µs+0s) by Foswiki::WebFilter::ok at line 54 of /var/www/foswikidev/core/lib/Foswiki/WebFilter.pm, avg 2µs/call # once (18µs+92µs) by Foswiki::new at line 2261 of /var/www/foswikidev/core/lib/Foswiki.pm # once (2µs+0s) by Foswiki::Func::isAnAdmin at line 1189 of /var/www/foswikidev/core/lib/Foswiki/Func.pm
sub isAdmin {
611353204µs my ( $this, $cUID ) = @_;
612
61335366µs return 0 unless defined $cUID;
614
6153531.07ms return $this->{isAdmin}->{$cUID}
616 if ( defined( $this->{isAdmin}->{$cUID} ) );
617
61812µs18µs my $mapping = $this->_getMapping($cUID);
# spent 8µs making 1 call to Foswiki::Users::_getMapping
61912µs my $otherMapping =
620 ( $mapping eq $this->{basemapping} )
621 ? $this->{mapping}
622 : $this->{basemapping};
623
62411µs if ( $mapping eq $otherMapping ) {
625 return $mapping->isAdmin($cUID);
626 }
62714µs184µs $this->{isAdmin}->{$cUID} =
# spent 84µs making 1 call to Foswiki::Users::BaseUserMapping::isAdmin
628 ( $mapping->isAdmin($cUID) || $otherMapping->isAdmin($cUID) );
62914µs return $this->{isAdmin}->{$cUID};
630}
631
632=begin TML
633
634---++ ObjectMethod isInUserList( $cUID, \@list ) -> $boolean
635
636Return true if $cUID is in a list of user *wikinames*, *logins* and group ids.
637
638The list may contain the conventional web specifiers (which are ignored).
639
640=cut
641
642sub isInUserList {
643 my ( $this, $cUID, $userlist ) = @_;
644
645 return 0 unless defined $userlist && defined $cUID;
646
647 foreach my $ident (@$userlist) {
648
649 # The Wildcard match. Any user matches the "*" identifier.
650 if ( $ident eq '*' ) {
651 return 1;
652 }
653
654 my $identCUID = $this->getCanonicalUserID($ident);
655
656 if ( defined $identCUID ) {
657 return 1 if ( $identCUID eq $cUID );
658 }
659 if ( $this->isGroup($ident) ) {
660 return 1 if ( $this->isInGroup( $cUID, $ident ) );
661 }
662 }
663 return 0;
664}
665
666=begin TML
667
668---++ ObjectMethod getLoginName($cUID) -> $login
669
670Get the login name of a user. Returns undef if the user is not known.
671
672=cut
673
674
# spent 210µs (150+60) within Foswiki::Users::getLoginName which was called 48 times, avg 4µs/call: # 42 times (120µs+11µs) by Foswiki::Plugin::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Plugin.pm:257] at line 250 of /var/www/foswikidev/core/lib/Foswiki/Plugin.pm, avg 3µs/call # 3 times (22µs+49µs) by Foswiki::Render::renderRevisionInfo at line 822 of /var/www/foswikidev/core/lib/Foswiki/Render.pm, avg 24µs/call # 2 times (6µs+0s) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/USERINFO.pm:26] at line 22 of /var/www/foswikidev/core/lib/Foswiki/Macros/USERINFO.pm, avg 3µs/call # once (3µs+0s) by Foswiki::Logger::setCommonFields at line 145 of /var/www/foswikidev/core/lib/Foswiki/Logger.pm
sub getLoginName {
6754824µs my ( $this, $cUID ) = @_;
676
677489µs return unless defined($cUID);
678
67948164µs return $this->{cUID2Login}->{$cUID}
680 if ( defined( $this->{cUID2Login}->{$cUID} ) );
681
682 ASSERT( $this->{basemapping} ) if DEBUG;
68323µs219µs my $mapping = $this->_getMapping($cUID);
# spent 19µs making 2 calls to Foswiki::Users::_getMapping, avg 9µs/call
6842500ns my $login;
68526µs241µs if ( $cUID && $mapping ) {
# spent 38µs making 1 call to Foswiki::Users::TopicUserMapping::getLoginName # spent 3µs making 1 call to Foswiki::Users::BaseUserMapping::getLoginName
686 $login = $mapping->getLoginName($cUID);
687 }
688
68921µs if ( defined $login ) {
69023µs $this->{cUID2Login}->{$cUID} = $login;
69122µs $this->{login2cUID}->{$login} = $cUID;
692 }
693
69428µs return $login;
695}
696
697=begin TML
698
699---++ ObjectMethod getWikiName($cUID) -> $wikiName
700
701Get the wikiname to display for a canonical user identifier.
702
703Can return undef if the user is not in the mapping system
704(or the special case from initialiseUser)
705
706=cut
707
708
# spent 136µs (101+35) within Foswiki::Users::getWikiName which was called 18 times, avg 8µs/call: # 7 times (18µs+0s) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/USERINFO.pm:42] at line 37 of /var/www/foswikidev/core/lib/Foswiki/Macros/USERINFO.pm, avg 2µs/call # 5 times (32µs+23µs) by Foswiki::Users::webDotWikiName at line 750, avg 11µs/call # 3 times (6µs+0s) by Foswiki::Render::renderRevisionInfo at line 821 of /var/www/foswikidev/core/lib/Foswiki/Render.pm, avg 2µs/call # 2 times (10µs+0s) by Foswiki::Func::getWikiName at line 1003 of /var/www/foswikidev/core/lib/Foswiki/Func.pm, avg 5µs/call # once (36µs+11µs) by Foswiki::new at line 2250 of /var/www/foswikidev/core/lib/Foswiki.pm
sub getWikiName {
709189µs my ( $this, $cUID ) = @_;
710183µs return 'UnknownUser' unless defined($cUID);
7111865µs return $this->{cUID2WikiName}->{$cUID}
712 if ( defined( $this->{cUID2WikiName}->{$cUID} ) );
713
7142500ns my $wikiname;
71523µs222µs my $mapping = $this->_getMapping($cUID);
# spent 22µs making 2 calls to Foswiki::Users::_getMapping, avg 11µs/call
71627µs213µs $wikiname = $mapping->getWikiName($cUID) if $mapping;
# spent 10µs making 1 call to Foswiki::Users::TopicUserMapping::getWikiName # spent 3µs making 1 call to Foswiki::Users::BaseUserMapping::getWikiName
717
718 #don't cache unknown users - it really makes a mess later.
71922µs if ( !defined($wikiname) ) {
720 if ( $Foswiki::cfg{RenderLoggedInButUnknownUsers} ) {
721 $wikiname = "UnknownUser (<nop>$cUID)";
722 }
723 else {
724 $wikiname = $cUID;
725 }
726 }
727 else {
728
729 # remove the web part
730 # SMELL: is this really needed?
731223µs $wikiname =~ s/^($Foswiki::cfg{UsersWebName}|%MAINWEB%|%USERSWEB%)\.//;
732
73322µs $this->{cUID2WikiName}->{$cUID} = $wikiname;
73422µs $this->{wikiName2cUID}->{$wikiname} = $cUID;
735 }
73628µs return $wikiname;
737}
738
739=begin TML
740
741---++ ObjectMethod webDotWikiName($cUID) -> $webDotWiki
742
743Return the fully qualified wikiname of the user
744
745=cut
746
747
# spent 89µs (34+55) within Foswiki::Users::webDotWikiName which was called 5 times, avg 18µs/call: # 3 times (21µs+48µs) by Foswiki::Render::renderRevisionInfo at line 820 of /var/www/foswikidev/core/lib/Foswiki/Render.pm, avg 23µs/call # 2 times (13µs+7µs) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/USERINFO.pm:51] at line 45 of /var/www/foswikidev/core/lib/Foswiki/Macros/USERINFO.pm, avg 10µs/call
sub webDotWikiName {
74854µs my ( $this, $cUID ) = @_;
749
750528µs555µs return $Foswiki::cfg{UsersWebName} . '.' . $this->getWikiName($cUID);
# spent 55µs making 5 calls to Foswiki::Users::getWikiName, avg 11µs/call
751}
752
753=begin TML
754
755---++ ObjectMethod userExists($cUID) -> $boolean
756
757Determine if the user already exists or not. A user exists if they are
758known to to the user mapper.
759
760=cut
761
762sub userExists {
763 my ( $this, $cUID ) = @_;
764 return $this->_getMapping($cUID)->userExists($cUID);
765}
766
767=begin TML
768
769---++ ObjectMethod eachUser() -> Foswiki::Iterator of cUIDs
770
771Get an iterator over the list of all the registered users *not* including
772groups.
773
774list of canonical_ids ???
775
776Use it as follows:
777<verbatim>
778 my $iterator = $umm->eachUser();
779 while ($iterator->hasNext()) {
780 my $user = $iterator->next();
781 ...
782 }
783</verbatim>
784
785=cut
786
787sub eachUser {
788 my $this = shift;
789 my @list =
790 ( $this->{basemapping}->eachUser(@_), $this->{mapping}->eachUser(@_) );
791 return new Foswiki::AggregateIterator( \@list, 1 );
792
793 return shift->{mapping}->eachUser(@_);
794}
795
796=begin TML
797
798---++ ObjectMethod eachGroup() -> $iterator
799
800Get an iterator over the list of all the group names.
801
802=cut
803
804sub eachGroup {
805 my $this = shift;
806 my @list =
807 ( $this->{basemapping}->eachGroup(@_), $this->{mapping}->eachGroup(@_) );
808 return new Foswiki::AggregateIterator( \@list, 1 );
809}
810
811=begin TML
812
813---++ ObjectMethod eachGroupMember($group) -> $iterator
814
815Return a iterator of user ids that are members of this group.
816Should only be called on groups.
817
818Note that groups may be defined recursively, so a group may contain other
819groups. This method should *only* return users i.e. all contained groups
820should be fully expanded.
821
822=cut
823
824sub eachGroupMember {
825 my $this = shift;
826 my @list = (
827 $this->{basemapping}->eachGroupMember(@_),
828 $this->{mapping}->eachGroupMember(@_)
829 );
830 return new Foswiki::AggregateIterator( \@list, 1 );
831}
832
833=begin TML
834
835---++ ObjectMethod isGroup($name) -> boolean
836
837Establish if a $name refers to a group or not. If $name is not
838a group name it will probably be a canonical user id, though that
839should not be assumed.
840
841=cut
842
843
# spent 649µs (364+285) within Foswiki::Users::isGroup which was called 62 times, avg 10µs/call: # 62 times (364µs+285µs) by Foswiki::Func::eachGroupMember at line 1350 of /var/www/foswikidev/core/lib/Foswiki/Func.pm, avg 10µs/call
sub isGroup {
8446213µs my $this = shift;
84562267µs124285µs return ( $this->{basemapping}->isGroup(@_) )
# spent 165µs making 62 calls to Foswiki::Users::TopicUserMapping::isGroup, avg 3µs/call # spent 120µs making 62 calls to Foswiki::Users::BaseUserMapping::isGroup, avg 2µs/call
846 || ( $this->{mapping}->isGroup(@_) );
847}
848
849=begin TML
850
851---++ ObjectMethod isInGroup( $cUID, $group, $options) -> $boolean
852
853Test if the user identified by $cUID is in the given group. Options
854is a hash array of options effecting the search. Available options are:
855
856 * =expand => 1= 0/1 - should nested groups be expanded when searching for the user. Default is 1, to expand nested groups.
857
858=cut
859
860sub isInGroup {
861 my ( $this, $cUID, $group, $options ) = @_;
862 return unless ( defined($cUID) );
863
864 my $expand = $options->{expand};
865 $expand = 1 unless ( defined $expand );
866
867 my $mapping = $this->_getMapping($cUID);
868 my $otherMapping =
869 ( $mapping eq $this->{basemapping} )
870 ? $this->{mapping}
871 : $this->{basemapping};
872 return 1 if $mapping->isInGroup( $cUID, $group, { expand => $expand } );
873
874 return $otherMapping->isInGroup( $cUID, $group, { expand => $expand } )
875 if ( $otherMapping ne $mapping );
876}
877
878=begin TML
879
880---++ ObjectMethod eachMembership($cUID) -> $iterator
881
882Return an iterator over the groups that $cUID
883is a member of.
884
885=cut
886
887sub eachMembership {
888 my ( $this, $cUID ) = @_;
889
890 my $mapping = $this->_getMapping($cUID);
891 my $wikiname = $mapping->getWikiName($cUID);
892
893 #stop if the user has no wikiname (generally means BugsItem4771)
894 unless ( defined($wikiname) ) {
895 require Foswiki::ListIterator;
896 return new Foswiki::ListIterator( \() );
897 }
898
899 my $otherMapping =
900 ( $mapping eq $this->{basemapping} )
901 ? $this->{mapping}
902 : $this->{basemapping};
903 if ( $mapping eq $otherMapping ) {
904
905 # only using BaseMapping.
906 return $mapping->eachMembership($cUID);
907 }
908
909 my @list =
910 ( $mapping->eachMembership($cUID), $otherMapping->eachMembership($cUID) );
911 return new Foswiki::AggregateIterator( \@list, 1 );
912}
913
914=begin TML
915
916---++ ObjectMethod groupAllowsView($group) -> boolean
917
918returns 1 if the group is able to be modified by the current logged in user
919
920=cut
921
922sub groupAllowsView {
923 my $this = shift;
924 my $group = shift;
925 my $mapping = $this->{mapping};
926 return $mapping->groupAllowsView($group);
927}
928
929=begin TML
930
931---++ ObjectMethod groupAllowsChange($group, $cuid) -> boolean
932
933returns 1 if the group is able to be modified by the current logged in user
934
935=cut
936
937sub groupAllowsChange {
938 my $this = shift;
939 my $group = shift;
940 my $cuid = shift || $this->{session}->{user};
941
942 return ( $this->{basemapping}->groupAllowsChange( $group, $cuid )
943 and $this->{mapping}->groupAllowsChange( $group, $cuid ) );
944}
945
946=begin TML
947
948---++ ObjectMethod addToGroup( $cuid, $group, $create ) -> $boolean
949adds the user specified by the cuid to the group.
950If the group does not exist, it will return false and do nothing, unless the create flag is set.
951
952=cut
953
954sub addUserToGroup {
955 my ( $this, $cuid, $group, $create ) = @_;
956 my $mapping = $this->{mapping};
957 return $mapping->addUserToGroup( $cuid, $group, $create );
958}
959
960=begin TML
961
962---++ ObjectMethod removeFromGroup( $cuid, $group ) -> $boolean
963
964=cut
965
966sub removeUserFromGroup {
967 my ( $this, $cuid, $group ) = @_;
968 my $mapping = $this->{mapping};
969 return $mapping->removeUserFromGroup( $cuid, $group );
970}
971
972=begin TML
973
974---++ ObjectMethod checkLogin( $login, $passwordU ) -> $boolean
975
976Finds if the password is valid for the given user. This method is
977called using the login name rather than the $cUID so that it can be called
978with a user who can be authenticated, but may not be mappable to a
979cUID (yet).
980
981Returns 1 on success, undef on failure.
982
983TODO: add special check for BaseMapping admin user's login, and if
984its there (and we're in sudo_context?) use that..
985
986=cut
987
988sub checkPassword {
989 my ( $this, $login, $pw ) = @_;
990 my $mapping = $this->_getMapping( undef, $login, undef, 0 );
991 return $mapping->checkPassword( $login, $pw );
992}
993
994=begin TML
995
996---++ ObjectMethod setPassword( $cUID, $newPassU, $oldPassU ) -> $boolean
997
998If the $oldPassU matches matches the user's password, then it will
999replace it with $newPassU.
1000
1001If $oldPassU is not correct and not 1, will return 0.
1002
1003If $oldPassU is 1, will force the change irrespective of
1004the existing password, adding the user if necessary.
1005
1006Otherwise returns 1 on success, undef on failure.
1007
1008=cut
1009
1010sub setPassword {
1011 my ( $this, $cUID, $newPassU, $oldPassU ) = @_;
1012 ASSERT($cUID) if DEBUG;
1013 return $this->_getMapping($cUID)
1014 ->setPassword( $this->getLoginName($cUID), $newPassU, $oldPassU );
1015}
1016
1017=begin TML
1018
1019---++ ObjectMethod passwordError($cUID) -> $string
1020
1021Returns a string indicating the error that happened in the password handler
1022The cUID is used to determine which mapper is handling the user. If called
1023without a cUID, then the Base mapping is used.
1024
1025TODO: these delayed error's should be replaced with Exceptions.
1026
1027returns undef if no error
1028
1029=cut
1030
1031sub passwordError {
1032 my ( $this, $cUID ) = @_;
1033 return $this->_getMapping($cUID)->passwordError();
1034}
1035
1036=begin TML
1037
1038---++ ObjectMethod removeUser( $cUID ) -> $boolean
1039
1040Delete the users entry. Removes the user from the password
1041manager and user mapping manager. Does *not* remove their personal
1042topics, which may still be linked.
1043
1044=cut
1045
1046sub removeUser {
1047 my ( $this, $cUID ) = @_;
1048 $this->_getMapping($cUID)->removeUser($cUID);
1049}
1050
105113µs1;
1052__END__