Filename | /var/www/foswikidev/core/lib/Foswiki/Users.pm |
Statements | Executed 4794 statements in 11.5ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 5.80ms | 8.55ms | new | Foswiki::Users::
1 | 1 | 1 | 5.16ms | 9.30ms | BEGIN@64 | Foswiki::Users::
1066 | 1 | 1 | 1.59ms | 1.59ms | mapLogin2cUID | Foswiki::Users::
353 | 5 | 5 | 1.07ms | 1.16ms | isAdmin | Foswiki::Users::
1 | 1 | 1 | 464µs | 938µs | BEGIN@63 | Foswiki::Users::
62 | 1 | 1 | 364µs | 649µs | isGroup | Foswiki::Users::
48 | 4 | 4 | 150µs | 210µs | getLoginName | Foswiki::Users::
18 | 5 | 5 | 101µs | 136µs | getWikiName | Foswiki::Users::
8 | 4 | 1 | 89µs | 32.0ms | _getMapping | Foswiki::Users::
6 | 4 | 4 | 71µs | 32.1ms | getCanonicalUserID | Foswiki::Users::
1 | 1 | 1 | 53µs | 1.35ms | finish | Foswiki::Users::
5 | 2 | 2 | 34µs | 89µs | webDotWikiName | Foswiki::Users::
10 | 1 | 1 | 27µs | 27µs | getLoginManager | Foswiki::Users::
3 | 2 | 1 | 25µs | 34µs | getCGISession | Foswiki::Users::
1 | 1 | 1 | 15µs | 3.11ms | initialiseUser | Foswiki::Users::
1 | 1 | 1 | 14µs | 168µs | loadSession | Foswiki::Users::
1 | 1 | 1 | 13µs | 26µs | BEGIN@59 | Foswiki::Users::
1 | 1 | 1 | 13µs | 34µs | BEGIN@313 | Foswiki::Users::
1 | 1 | 1 | 11µs | 14µs | BEGIN@408 | Foswiki::Users::
1 | 1 | 1 | 10µs | 12µs | BEGIN@406 | Foswiki::Users::
1 | 1 | 1 | 9µs | 37µs | BEGIN@61 | Foswiki::Users::
1 | 1 | 1 | 9µs | 13µs | BEGIN@60 | Foswiki::Users::
1 | 1 | 1 | 8µs | 8µs | supportsRegistration | Foswiki::Users::
1 | 1 | 1 | 5µs | 5µs | BEGIN@69 | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | addUser | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | addUserToGroup | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | checkPassword | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | eachGroup | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | eachGroupMember | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | eachMembership | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | eachUser | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | findUserByEmail | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | findUserByWikiName | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | getEmails | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | groupAllowsChange | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | groupAllowsView | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | isInGroup | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | isInUserList | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | loginTemplateName | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | passwordError | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | randomPassword | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | removeUser | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | removeUserFromGroup | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | setEmails | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | setPassword | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | userExists | Foswiki::Users::
0 | 0 | 0 | 0s | 0s | validateRegistrationField | Foswiki::Users::
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 | ||||
6 | This package provides services for the lookup and manipulation of login and | ||||
7 | wiki names of users, and their authentication. | ||||
8 | |||||
9 | It is a Facade that presents a common interface to the User Mapping | ||||
10 | and Password modules. The rest of the core should *only* use the methods | ||||
11 | of this package, and should *never* call the mapping or password managers | ||||
12 | directly. | ||||
13 | |||||
14 | Foswiki uses the concept of a _login name_ which is used to authenticate a | ||||
15 | user. A login name maps to a _wiki name_ that is used to identify the user | ||||
16 | for display. Each login name is unique to a single user, though several | ||||
17 | login names may map to the same wiki name. | ||||
18 | |||||
19 | Using this module (and the associated plug-in user mapper) Foswiki supports | ||||
20 | the concept of _groups_. Groups are sets of login names that are treated | ||||
21 | equally for the purposes of access control. Group names do not have to be | ||||
22 | wiki names, though it is helpful for display if they are. | ||||
23 | |||||
24 | Internally in the code Foswiki uses something referred to as a _canonical user | ||||
25 | id_ or just _user id_. The user id is also used externally to uniquely identify | ||||
26 | the user when (for example) recording topic histories. The user id is *usually* | ||||
27 | just the login name, but it doesn't need to be. It just has to be a unique | ||||
28 | 7-bit alphanumeric and underscore string that can be mapped to/from login | ||||
29 | and wiki names by the user mapper. | ||||
30 | |||||
31 | The canonical user id should *never* be seen by a user. On the other hand, | ||||
32 | core code should never use anything *but* a canonical user id to refer | ||||
33 | to 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 | |||||
57 | package Foswiki::Users; | ||||
58 | |||||
59 | 2 | 27µs | 2 | 40µ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 # spent 26µs making 1 call to Foswiki::Users::BEGIN@59
# spent 13µs making 1 call to strict::import |
60 | 2 | 23µs | 2 | 18µ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 # spent 13µs making 1 call to Foswiki::Users::BEGIN@60
# spent 4µs making 1 call to warnings::import |
61 | 2 | 28µs | 2 | 66µ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 # spent 37µs making 1 call to Foswiki::Users::BEGIN@61
# spent 28µs making 1 call to Exporter::import |
62 | |||||
63 | 2 | 95µs | 1 | 938µ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 # spent 938µs making 1 call to Foswiki::Users::BEGIN@63 |
64 | 2 | 130µs | 1 | 9.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 # 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 | ||||
70 | 1 | 5µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
71 | require locale; | ||||
72 | import locale(); | ||||
73 | } | ||||
74 | 1 | 663µs | 1 | 5µs | } # spent 5µs making 1 call to Foswiki::Users::BEGIN@69 |
75 | |||||
76 | =begin TML | ||||
77 | |||||
78 | ---++ ClassMethod new ($session) | ||||
79 | Construct the user management object that is the facade to the BaseUserMapping | ||||
80 | and 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 | ||||
85 | 1 | 1µs | my ( $class, $session ) = @_; | ||
86 | 1 | 7µs | my $this = bless( { session => $session }, $class ); | ||
87 | |||||
88 | # making basemapping | ||||
89 | 1 | 2µs | my $implBaseUserMappingManager = $Foswiki::cfg{BaseUserMappingManager} | ||
90 | || 'Foswiki::Users::BaseUserMapping'; | ||||
91 | 1 | 21µs | eval "require $implBaseUserMappingManager"; # spent 2µs executing statements in string eval | ||
92 | 1 | 900ns | die $@ if $@; | ||
93 | 1 | 6µs | 1 | 74µs | $this->{basemapping} = $implBaseUserMappingManager->new($session); # spent 74µs making 1 call to Foswiki::Users::BaseUserMapping::new |
94 | |||||
95 | 1 | 2µs | my $implUserMappingManager = $Foswiki::cfg{UserMappingManager}; | ||
96 | 1 | 1µs | $implUserMappingManager = 'Foswiki::Users::TopicUserMapping' | ||
97 | if ( $implUserMappingManager eq 'none' ); | ||||
98 | |||||
99 | 1 | 800ns | if ( $implUserMappingManager eq 'Foswiki::Users::BaseUserMapping' ) { | ||
100 | $this->{mapping} = $this->{basemapping}; #TODO: probly make undef.. | ||||
101 | } | ||||
102 | else { | ||||
103 | 1 | 20µs | eval "require $implUserMappingManager"; # spent 81µs executing statements in string eval | ||
104 | 1 | 600ns | die $@ if $@; | ||
105 | 1 | 12µs | 1 | 716µs | $this->{mapping} = $implUserMappingManager->new($session); # spent 716µs making 1 call to Foswiki::Users::TopicUserMapping::new |
106 | } | ||||
107 | |||||
108 | 1 | 4µs | 1 | 880µ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 | ||||
114 | 1 | 1µs | $this->{cUID2WikiName} = {}; | ||
115 | 1 | 1µs | $this->{cUID2Login} = {}; | ||
116 | 1 | 800ns | $this->{isAdmin} = {}; | ||
117 | |||||
118 | # the UI for rego supported/not is different from rego temporarily | ||||
119 | # turned off | ||||
120 | 1 | 3µs | 1 | 8µs | if ( $this->supportsRegistration() ) { # spent 8µs making 1 call to Foswiki::Users::supportsRegistration |
121 | 1 | 1µs | 1 | 3µs | $session->enterContext('registration_supported'); # spent 3µs making 1 call to Foswiki::enterContext |
122 | 1 | 2µs | 1 | 2µs | $session->enterContext('registration_enabled') # spent 2µs making 1 call to Foswiki::enterContext |
123 | if $Foswiki::cfg{Register}{EnableNewUserRegistration}; | ||||
124 | } | ||||
125 | |||||
126 | 1 | 4µs | return $this; | ||
127 | } | ||||
128 | |||||
129 | =begin TML | ||||
130 | |||||
131 | ---++ ObjectMethod loadSession() | ||||
132 | |||||
133 | Setup the cgi session, from a cookie or the url. this may return | ||||
134 | the login, but even if it does, plugins will get the chance to | ||||
135 | override (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 | ||||
140 | 1 | 1µ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. | ||||
145 | 1 | 7µs | 1 | 153µs | my $remoteUser = $this->{loginManager}->loadSession( $defaultUser, $this ); # spent 153µs making 1 call to Foswiki::LoginManager::loadSession |
146 | |||||
147 | 1 | 4µs | return $remoteUser; | ||
148 | } | ||||
149 | |||||
150 | =begin TML | ||||
151 | |||||
152 | ---++ ObjectMethod finish() | ||||
153 | Break 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 | ||||
161 | 1 | 500ns | my $this = shift; | ||
162 | |||||
163 | 1 | 11µs | 1 | 146µs | $this->{loginManager}->finish() if $this->{loginManager}; # spent 146µs making 1 call to Foswiki::LoginManager::finish |
164 | 1 | 6µs | 1 | 46µs | $this->{basemapping}->finish() if $this->{basemapping}; # spent 46µs making 1 call to Foswiki::Users::BaseUserMapping::finish |
165 | |||||
166 | 1 | 6µs | 1 | 1.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 | |||||
170 | 1 | 6µs | undef $this->{loginManager}; | ||
171 | 1 | 6µs | undef $this->{basemapping}; | ||
172 | 1 | 5µs | undef $this->{mapping}; | ||
173 | 1 | 500ns | undef $this->{session}; | ||
174 | 1 | 2µs | undef $this->{cUID2WikiName}; | ||
175 | 1 | 700ns | undef $this->{cUID2Login}; | ||
176 | 1 | 900ns | undef $this->{wikiName2cUID}; | ||
177 | 1 | 1µs | undef $this->{login2cUID}; | ||
178 | 1 | 4µs | undef $this->{isAdmin}; | ||
179 | |||||
180 | } | ||||
181 | |||||
182 | =begin TML | ||||
183 | |||||
184 | ---++ ObjectMethod loginTemplateName () -> templateFile | ||||
185 | |||||
186 | allows UserMappings to come with customised login screens - that should preffereably only over-ride the UI function | ||||
187 | |||||
188 | =cut | ||||
189 | |||||
190 | sub 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 | ||||
201 | 8 | 6µs | my ( $this, $cUID, $login, $wikiname, $noFallBack ) = @_; | ||
202 | |||||
203 | 8 | 2µs | $login = '' unless defined $login; | ||
204 | 8 | 3µs | $wikiname = '' unless defined $wikiname; | ||
205 | |||||
206 | 8 | 31µ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). | ||||
212 | 8 | 29µs | 8 | 26µ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 | |||||
215 | 3 | 15µs | 3 | 31.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 | ||||
235 | 1 | 700ns | my ($this) = @_; | ||
236 | 1 | 4µs | 1 | 800ns | return $this->{mapping}->supportsRegistration(); # spent 800ns making 1 call to Foswiki::Users::TopicUserMapping::supportsRegistration |
237 | } | ||||
238 | |||||
239 | =begin TML | ||||
240 | |||||
241 | ---++ ObjectMethod validateRegistrationField ( $field, $value ) -> text | ||||
242 | |||||
243 | Return the registration formfield sanitized by the mapper, or oops thrown to block the registration. | ||||
244 | |||||
245 | =cut | ||||
246 | |||||
247 | sub validateRegistrationField { | ||||
248 | my ($this) = shift; | ||||
249 | return $this->{mapping}->validateRegistrationField(@_); | ||||
250 | } | ||||
251 | |||||
252 | =begin TML | ||||
253 | |||||
254 | ---++ ObjectMethod initialiseUser ($login) -> $cUID | ||||
255 | |||||
256 | Given a login (which must have been authenticated) determine the cUID that | ||||
257 | corresponds 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 | ||||
263 | 1 | 900ns | my ( $this, $login ) = @_; | ||
264 | |||||
265 | # For compatibility with older ways of building login managers, | ||||
266 | # plugins can provide an alternate login name. | ||||
267 | 1 | 4µs | 1 | 3.06ms | my $plogin = $this->{session}->{plugins}->load(); # spent 3.06ms making 1 call to Foswiki::Plugins::load |
268 | |||||
269 | #Monitor::MARK("Plugins loaded"); | ||||
270 | |||||
271 | 1 | 700ns | $login = $plogin if $plogin; | ||
272 | |||||
273 | 1 | 200ns | my $cUID; | ||
274 | 1 | 1µs | if ( defined($login) && $login ne '' ) { | ||
275 | |||||
276 | # In the case of a user mapper that accepts any identifier as | ||||
277 | # a cUID, | ||||
278 | 1 | 2µs | 1 | 27µ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 | ||||
282 | 1 | 300ns | 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. | ||||
307 | 1 | 200ns | $cUID ||= $this->getCanonicalUserID( $Foswiki::cfg{DefaultUserLogin} ); | ||
308 | |||||
309 | 1 | 3µs | return $cUID; | ||
310 | } | ||||
311 | |||||
312 | # global used by test harness to give predictable results | ||||
313 | 2 | 242µs | 2 | 56µ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 # 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() | ||||
318 | Static function that returns a random password. This function is not used | ||||
319 | in this module; it is provided as a service for other modules, such as | ||||
320 | custom mappers and registration modules. | ||||
321 | |||||
322 | =cut | ||||
323 | |||||
324 | sub 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 | |||||
350 | Add a new Foswiki user identity, returning the canonical user id for the new | ||||
351 | user. Used ONLY for user registration. | ||||
352 | |||||
353 | The user is added to the password system (if there is one, and if it accepts | ||||
354 | changes). If the user already exists in the password system, then the password | ||||
355 | is checked and an exception thrown if it doesn't match. If there is no | ||||
356 | existing user, and no password is given, a random password is generated. | ||||
357 | |||||
358 | $login can be undef; $wikiname must always have a value. | ||||
359 | |||||
360 | The return value is the canonical user id that is used | ||||
361 | by Foswiki to identify the user. | ||||
362 | |||||
363 | =cut | ||||
364 | |||||
365 | sub 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 | |||||
390 | This function maps an arbitrary string into a valid cUID. The transformation | ||||
391 | is reversible, but the function is not idempotent (a cUID passed to this | ||||
392 | function will NOT be returned unchanged). The generated cUID will be unique | ||||
393 | for the given login name. | ||||
394 | |||||
395 | This static function is designed to be called from custom user mappers that | ||||
396 | support 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 | ||||
401 | 1066 | 222µs | my $cUID = shift; | ||
402 | |||||
403 | ASSERT( defined($cUID) ) if DEBUG; | ||||
404 | |||||
405 | # use bytes to ignore character encoding | ||||
406 | 2 | 54µs | 2 | 15µ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 # spent 12µs making 1 call to Foswiki::Users::BEGIN@406
# spent 2µs making 1 call to bytes::import |
407 | 1066 | 484µs | $cUID =~ s/([^a-zA-Z0-9])/'_'.sprintf('%02x', ord($1))/ge; | ||
408 | 2 | 1.61ms | 2 | 17µ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 # spent 14µs making 1 call to Foswiki::Users::BEGIN@408
# spent 3µs making 1 call to bytes::unimport |
409 | 1066 | 5.48ms | return $cUID; | ||
410 | } | ||||
411 | |||||
412 | =begin TML | ||||
413 | |||||
414 | ---++ ObjectMethod getCGISession() | ||||
415 | Get 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 | ||||
420 | 3 | 2µs | my $this = shift; | ||
421 | 3 | 24µs | 3 | 10µ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 | |||||
428 | Get the Foswiki::LoginManager object associated with this session, if there is | ||||
429 | one. 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 | ||||
434 | 10 | 4µs | my $this = shift; | ||
435 | 10 | 41µs | return $this->{loginManager}; | ||
436 | } | ||||
437 | |||||
438 | =begin TML | ||||
439 | |||||
440 | ---++ ObjectMethod getCanonicalUserID( $identifier ) -> $cUID | ||||
441 | |||||
442 | Works 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 | |||||
446 | The canonical user ID is an alphanumeric string that is unique | ||||
447 | to the login name, and can be mapped back to a login name and the | ||||
448 | corresponding wiki name using the methods of this class. | ||||
449 | |||||
450 | Note that if the login name to wiki name mapping is not 1:1, this | ||||
451 | method will map a wikiname to one of the login names that corresponds | ||||
452 | to the wiki name, but there is no guarantee which one. | ||||
453 | |||||
454 | Returns 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 | ||||
462 | 6 | 5µs | my ( $this, $identifier ) = @_; | ||
463 | 6 | 1µs | my $cUID; | ||
464 | |||||
465 | ASSERT( defined $identifier ) if DEBUG; | ||||
466 | |||||
467 | # Someone we already know? | ||||
468 | |||||
469 | 6 | 11µ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 | ||||
478 | 3 | 8µs | 3 | 32.0ms | my $mapping = $this->_getMapping( undef, $identifier, undef, 1 ); # spent 32.0ms making 3 calls to Foswiki::Users::_getMapping, avg 10.7ms/call |
479 | 3 | 2µs | if ($mapping) { | ||
480 | 3 | 27µs | 6 | 25µ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 | |||||
497 | 3 | 1µ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 | } | ||||
512 | 6 | 20µs | return $cUID; | ||
513 | } | ||||
514 | |||||
515 | =begin TML | ||||
516 | |||||
517 | ---++ ObjectMethod findUserByWikiName( $wn ) -> \@users | ||||
518 | * =$wn= - wikiname to look up | ||||
519 | Return a list of canonical user names for the users that have this wikiname. | ||||
520 | Since a single wikiname might be used by multiple login ids, we need a list. | ||||
521 | |||||
522 | If $wn is the name of a group, the group will *not* be expanded. | ||||
523 | |||||
524 | =cut | ||||
525 | |||||
526 | sub 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 | ||||
542 | Return a list of canonical user names for the users that have this email | ||||
543 | registered with the user mapping managers. | ||||
544 | |||||
545 | =cut | ||||
546 | |||||
547 | sub 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 | |||||
561 | If $name is a cUID, return their email addresses. If it is a group, | ||||
562 | return the addresses of everyone in the group. | ||||
563 | |||||
564 | The password manager and user mapping manager are both consulted for emails | ||||
565 | for each user (where they are actually found is implementation defined). | ||||
566 | |||||
567 | Duplicates are removed from the list. | ||||
568 | |||||
569 | =cut | ||||
570 | |||||
571 | sub 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 | |||||
586 | Set the email address(es) for the given user. | ||||
587 | The password manager is tried first, and if it doesn't want to know the | ||||
588 | user mapping manager is tried. | ||||
589 | |||||
590 | =cut | ||||
591 | |||||
592 | sub 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 | |||||
603 | True 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 | ||||
611 | 353 | 204µs | my ( $this, $cUID ) = @_; | ||
612 | |||||
613 | 353 | 66µs | return 0 unless defined $cUID; | ||
614 | |||||
615 | 353 | 1.07ms | return $this->{isAdmin}->{$cUID} | ||
616 | if ( defined( $this->{isAdmin}->{$cUID} ) ); | ||||
617 | |||||
618 | 1 | 2µs | 1 | 8µs | my $mapping = $this->_getMapping($cUID); # spent 8µs making 1 call to Foswiki::Users::_getMapping |
619 | 1 | 2µs | my $otherMapping = | ||
620 | ( $mapping eq $this->{basemapping} ) | ||||
621 | ? $this->{mapping} | ||||
622 | : $this->{basemapping}; | ||||
623 | |||||
624 | 1 | 1µs | if ( $mapping eq $otherMapping ) { | ||
625 | return $mapping->isAdmin($cUID); | ||||
626 | } | ||||
627 | 1 | 4µs | 1 | 84µs | $this->{isAdmin}->{$cUID} = # spent 84µs making 1 call to Foswiki::Users::BaseUserMapping::isAdmin |
628 | ( $mapping->isAdmin($cUID) || $otherMapping->isAdmin($cUID) ); | ||||
629 | 1 | 4µs | return $this->{isAdmin}->{$cUID}; | ||
630 | } | ||||
631 | |||||
632 | =begin TML | ||||
633 | |||||
634 | ---++ ObjectMethod isInUserList( $cUID, \@list ) -> $boolean | ||||
635 | |||||
636 | Return true if $cUID is in a list of user *wikinames*, *logins* and group ids. | ||||
637 | |||||
638 | The list may contain the conventional web specifiers (which are ignored). | ||||
639 | |||||
640 | =cut | ||||
641 | |||||
642 | sub 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 | |||||
670 | Get 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 | ||||
675 | 48 | 24µs | my ( $this, $cUID ) = @_; | ||
676 | |||||
677 | 48 | 9µs | return unless defined($cUID); | ||
678 | |||||
679 | 48 | 164µs | return $this->{cUID2Login}->{$cUID} | ||
680 | if ( defined( $this->{cUID2Login}->{$cUID} ) ); | ||||
681 | |||||
682 | ASSERT( $this->{basemapping} ) if DEBUG; | ||||
683 | 2 | 3µs | 2 | 19µs | my $mapping = $this->_getMapping($cUID); # spent 19µs making 2 calls to Foswiki::Users::_getMapping, avg 9µs/call |
684 | 2 | 500ns | my $login; | ||
685 | 2 | 6µs | 2 | 41µ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 | |||||
689 | 2 | 1µs | if ( defined $login ) { | ||
690 | 2 | 3µs | $this->{cUID2Login}->{$cUID} = $login; | ||
691 | 2 | 2µs | $this->{login2cUID}->{$login} = $cUID; | ||
692 | } | ||||
693 | |||||
694 | 2 | 8µs | return $login; | ||
695 | } | ||||
696 | |||||
697 | =begin TML | ||||
698 | |||||
699 | ---++ ObjectMethod getWikiName($cUID) -> $wikiName | ||||
700 | |||||
701 | Get the wikiname to display for a canonical user identifier. | ||||
702 | |||||
703 | Can 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 | ||||
709 | 18 | 9µs | my ( $this, $cUID ) = @_; | ||
710 | 18 | 3µs | return 'UnknownUser' unless defined($cUID); | ||
711 | 18 | 65µs | return $this->{cUID2WikiName}->{$cUID} | ||
712 | if ( defined( $this->{cUID2WikiName}->{$cUID} ) ); | ||||
713 | |||||
714 | 2 | 500ns | my $wikiname; | ||
715 | 2 | 3µs | 2 | 22µs | my $mapping = $this->_getMapping($cUID); # spent 22µs making 2 calls to Foswiki::Users::_getMapping, avg 11µs/call |
716 | 2 | 7µs | 2 | 13µ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. | ||||
719 | 2 | 2µ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? | ||||
731 | 2 | 23µs | $wikiname =~ s/^($Foswiki::cfg{UsersWebName}|%MAINWEB%|%USERSWEB%)\.//; | ||
732 | |||||
733 | 2 | 2µs | $this->{cUID2WikiName}->{$cUID} = $wikiname; | ||
734 | 2 | 2µs | $this->{wikiName2cUID}->{$wikiname} = $cUID; | ||
735 | } | ||||
736 | 2 | 8µs | return $wikiname; | ||
737 | } | ||||
738 | |||||
739 | =begin TML | ||||
740 | |||||
741 | ---++ ObjectMethod webDotWikiName($cUID) -> $webDotWiki | ||||
742 | |||||
743 | Return 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 | ||||
748 | 5 | 4µs | my ( $this, $cUID ) = @_; | ||
749 | |||||
750 | 5 | 28µs | 5 | 55µ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 | |||||
757 | Determine if the user already exists or not. A user exists if they are | ||||
758 | known to to the user mapper. | ||||
759 | |||||
760 | =cut | ||||
761 | |||||
762 | sub 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 | |||||
771 | Get an iterator over the list of all the registered users *not* including | ||||
772 | groups. | ||||
773 | |||||
774 | list of canonical_ids ??? | ||||
775 | |||||
776 | Use 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 | |||||
787 | sub 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 | |||||
800 | Get an iterator over the list of all the group names. | ||||
801 | |||||
802 | =cut | ||||
803 | |||||
804 | sub 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 | |||||
815 | Return a iterator of user ids that are members of this group. | ||||
816 | Should only be called on groups. | ||||
817 | |||||
818 | Note that groups may be defined recursively, so a group may contain other | ||||
819 | groups. This method should *only* return users i.e. all contained groups | ||||
820 | should be fully expanded. | ||||
821 | |||||
822 | =cut | ||||
823 | |||||
824 | sub 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 | |||||
837 | Establish if a $name refers to a group or not. If $name is not | ||||
838 | a group name it will probably be a canonical user id, though that | ||||
839 | should 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 | ||||
844 | 62 | 13µs | my $this = shift; | ||
845 | 62 | 267µs | 124 | 285µ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 | |||||
853 | Test if the user identified by $cUID is in the given group. Options | ||||
854 | is 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 | |||||
860 | sub 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 | |||||
882 | Return an iterator over the groups that $cUID | ||||
883 | is a member of. | ||||
884 | |||||
885 | =cut | ||||
886 | |||||
887 | sub 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 | |||||
918 | returns 1 if the group is able to be modified by the current logged in user | ||||
919 | |||||
920 | =cut | ||||
921 | |||||
922 | sub 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 | |||||
933 | returns 1 if the group is able to be modified by the current logged in user | ||||
934 | |||||
935 | =cut | ||||
936 | |||||
937 | sub 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 | ||||
949 | adds the user specified by the cuid to the group. | ||||
950 | If the group does not exist, it will return false and do nothing, unless the create flag is set. | ||||
951 | |||||
952 | =cut | ||||
953 | |||||
954 | sub 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 | |||||
966 | sub 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 | |||||
976 | Finds if the password is valid for the given user. This method is | ||||
977 | called using the login name rather than the $cUID so that it can be called | ||||
978 | with a user who can be authenticated, but may not be mappable to a | ||||
979 | cUID (yet). | ||||
980 | |||||
981 | Returns 1 on success, undef on failure. | ||||
982 | |||||
983 | TODO: add special check for BaseMapping admin user's login, and if | ||||
984 | its there (and we're in sudo_context?) use that.. | ||||
985 | |||||
986 | =cut | ||||
987 | |||||
988 | sub 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 | |||||
998 | If the $oldPassU matches matches the user's password, then it will | ||||
999 | replace it with $newPassU. | ||||
1000 | |||||
1001 | If $oldPassU is not correct and not 1, will return 0. | ||||
1002 | |||||
1003 | If $oldPassU is 1, will force the change irrespective of | ||||
1004 | the existing password, adding the user if necessary. | ||||
1005 | |||||
1006 | Otherwise returns 1 on success, undef on failure. | ||||
1007 | |||||
1008 | =cut | ||||
1009 | |||||
1010 | sub 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 | |||||
1021 | Returns a string indicating the error that happened in the password handler | ||||
1022 | The cUID is used to determine which mapper is handling the user. If called | ||||
1023 | without a cUID, then the Base mapping is used. | ||||
1024 | |||||
1025 | TODO: these delayed error's should be replaced with Exceptions. | ||||
1026 | |||||
1027 | returns undef if no error | ||||
1028 | |||||
1029 | =cut | ||||
1030 | |||||
1031 | sub passwordError { | ||||
1032 | my ( $this, $cUID ) = @_; | ||||
1033 | return $this->_getMapping($cUID)->passwordError(); | ||||
1034 | } | ||||
1035 | |||||
1036 | =begin TML | ||||
1037 | |||||
1038 | ---++ ObjectMethod removeUser( $cUID ) -> $boolean | ||||
1039 | |||||
1040 | Delete the users entry. Removes the user from the password | ||||
1041 | manager and user mapping manager. Does *not* remove their personal | ||||
1042 | topics, which may still be linked. | ||||
1043 | |||||
1044 | =cut | ||||
1045 | |||||
1046 | sub removeUser { | ||||
1047 | my ( $this, $cUID ) = @_; | ||||
1048 | $this->_getMapping($cUID)->removeUser($cUID); | ||||
1049 | } | ||||
1050 | |||||
1051 | 1 | 3µs | 1; | ||
1052 | __END__ |