head	1.5;
access;
symbols;
locks; strict;
comment	@# @;


1.5
date	2008.08.03.22.17.44;	author TWikiContributor;	state Exp;
branches;
next	1.4;

1.4
date	2008.01.22.03.21.27;	author TWikiContributor;	state Exp;
branches;
next	1.3;

1.3
date	2007.01.16.04.12.01;	author TWikiContributor;	state Exp;
branches;
next	1.2;

1.2
date	2006.06.25.16.26.33;	author TWikiContributor;	state Exp;
branches;
next	1.1;

1.1
date	2006.02.01.12.01.25;	author TWikiContributor;	state Exp;
branches;
next	;


desc
@new-topic
@


1.5
log
@buildrelease
@
text
@---+ Package =TWiki::Users=
This package provides services for the lookup and manipulation of login and
wiki names of users, and their authentication.

It is a Facade that presents a common interface to the User Mapping
and Password modules. The rest of the core should *only* use the methods
of this package, and should *never* call the mapping or password managers
directly.

TWiki uses the concept of a _login name_ which is used to authenticate a
user. A login name maps to a _wiki name_ that is used to identify the user
for display. Each login name is unique to a single user, though several
login names may map to the same wiki name.

Using this module (and the associated plug-in user mapper) TWiki supports
the concept of _groups_. Groups are sets of login names that are treated
equally for the purposes of access control. Group names do not have to be
wiki names, though it is helpful for display if they are.

Internally in the code TWiki uses something referred to as a _canonical user
id_ or just _user id_. The user id is also used externally to uniquely identify
the user when (for example) recording topic histories. The user id is *usually*
just the login name, but it doesn't need to be. It just has to be a unique
7-bit alphanumeric and underscore string that can be mapped to/from login
and wiki names by the user mapper.

The canonical user id should *never* be seen by a user. On the other hand,
core code should never use anything *but* a canonical user id to refer
to a user.

*Terminology*
   * A *login name* is the name used to log in to TWiki. Each login name is
     assumed to be unique to a human. The Password module is responsible for
     authenticating and manipulating login names.
   * A *canonical user id* is an internal TWiki representation of a user. Each
     canonical user id maps 1:1 to a login name.
   * A *wikiname* is how a user is displayed. Many user ids may map to a
     single wikiname. The user mapping module is responsible for mapping
     the user id to a wikiname.
   * A *group id* represents a group of users and other groups.
     The user mapping module is responsible for mapping from a group id to
     a list of canonical user ids for the users in that group.
   * An *email* is an email address asscoiated with a *login name*. A single
     login name may have many emails.
	 
*NOTE:* 
   * wherever the code references $cUID, its a canonical_id
   * wherever the code references $group, its a group_name
   * $name may be a group or a cUID


%TOC%

---++ ClassMethod *new* <tt>($session)</tt>
Construct the user management object that is the facade to the BaseUserMapping
and the user mapping chosen in the configuration.



---++ ObjectMethod *finish* <tt>()</tt>
Break circular references.



---++ ObjectMethod *loginTemplateName* <tt>() -> templateFile</tt>

allows UserMappings to come with customised login screens - that should preffereably only over-ride the UI function



---++ ObjectMethod *supportsRegistration* <tt>() -> boolean</tt>

#return 1 if the  main UserMapper supports registration (ie can create new users)



---++ ObjectMethod *initialiseUser* <tt>($login) -> $cUID</tt>

Given a login (which must have been authenticated) determine the cUID that
corresponds to that user. This method is used from TWiki.pm to map the
$REMOTE_USER to a cUID.



---++ randomPassword()
Static function that returns a random password. This function is not used
in this module; it is provided as a service for other modules, such as
custom mappers and registration modules.


---++ ObjectMethod *addUser* <tt>($login,$wikiname,$password,$emails) -> $cUID</tt>

   * =$login= - user login name. If =undef=, =$wikiname= will be used as
     the login name.
   * =$wikiname= - user wikiname. If =undef=, the user mapper will be asked
     to provide it.
   * =$password= - password. If undef, a password will be generated.

Add a new TWiki user identity, returning the canonical user id for the new
user. Used ONLY for user registration.

The user is added to the password system (if there is one, and if it accepts
changes). If the user already exists in the password system, then the password
is checked and an exception thrown if it doesn't match. If there is no
existing user, and no password is given, a random password is generated.

$login can be undef; $wikiname must always have a value.

The return value is the canonical user id that is used
by TWiki to identify the user.



---++ StaticMethod *mapLogin2cUID* <tt>($login) -> $cUID</tt>

This function maps an arbitrary string into a valid cUID. The transformation
is reversible, but the function is not idempotent (a cUID passed to this
function will NOT be returned unchanged). The generated cUID will be unique
for the given login name.

This static function is designed to be called from custom user mappers that
support 1:1 login-to-cUID mappings.



---++ ObjectMethod *getCanonicalUserID* <tt>($identifier) -> $cUID</tt>

Works out the TWiki canonical user identifier for the user who either
(1) logs in with the login name $identifier or (2) has the wikiname
$identifier.

The canonical user ID is an alphanumeric string that is unique
to the login name, and can be mapped back to a login name and the
corresponding wiki name using the methods of this class.

Note that if the login name to wiki name mapping is not 1:1, this
method will map a wikiname to one of the login names that corresponds
to the wiki name, but there is no guarantee which one.

Returns undef if the user does not exist.



---++ ObjectMethod *findUserByWikiName* <tt>($wn) -> \@@users</tt>
   * =$wn= - wikiname to look up
Return a list of canonical user names for the users that have this wikiname.
Since a single wikiname might be used by multiple login ids, we need a list.

If $wn is the name of a group, the group will *not* be expanded.



---++ ObjectMethod *findUserByEmail* <tt>($email) -> \@@users</tt>
   * =$email= - email address to look up
Return a list of canonical user names for the users that have this email
registered with the user mapping managers.



---++ ObjectMethod *getEmails* <tt>($name) -> @@emailAddress</tt>

If $name is a cUID, return their email addresses. If it is a group,
return the addresses of everyone in the group.

The password manager and user mapping manager are both consulted for emails
for each user (where they are actually found is implementation defined).

Duplicates are removed from the list.



---++ ObjectMethod *setEmails* <tt>($cUID,@@emails)</tt>

Set the email address(es) for the given user.
The password manager is tried first, and if it doesn't want to know the
user mapping manager is tried.



---++ ObjectMethod *isAdmin* <tt>($cUID) -> $boolean</tt>

True if the user is an admin
   * is $TWiki::cfg{SuperAdminGroup}
   * is a member of the $TWiki::cfg{SuperAdminGroup}



---++ ObjectMethod *isInList* <tt>($cUID,$list) -> $boolean</tt>

Return true if $cUID is in a list of user *wikinames*, *logins* and group ids.

The list may contain the conventional web specifiers (which are ignored).



---++ ObjectMethod *getLoginName* <tt>($cUID) -> $login</tt>

Get the login name of a user. Returns undef if the user is not known.



---++ ObjectMethod *getWikiName* <tt>($cUID) -> $wikiName</tt>

Get the wikiname to display for a canonical user identifier.

Can return undef if the user is not in the mapping system
(or the special case from initialiseUser)



---++ ObjectMethod *webDotWikiName* <tt>($cUID) -> $webDotWiki</tt>

Return the fully qualified wikiname of the user



---++ ObjectMethod *userExists* <tt>($cUID) -> $boolean</tt>

Determine if the user already exists or not. A user exists if they are
known to to the user mapper.



---++ ObjectMethod *eachUser* <tt>() -> TWiki::IteratorofcUIDs</tt>

Get an iterator over the list of all the registered users *not* including
groups.

list of canonical_ids ???

Use it as follows:
<verbatim>
    my $iterator = $umm->eachUser();
    while ($iterator->hasNext()) {
        my $user = $iterator->next();
        ...
    }
</verbatim>



---++ ObjectMethod *eachGroup* <tt>() -> TWiki::ListIteratorofgroupnames</tt>

Get an iterator over the list of all the groups.



---++ ObjectMethod *eachGroupMember* <tt>($group) -> $iterator</tt>

Return a iterator of user ids that are members of this group.
Should only be called on groups.

Note that groups may be defined recursively, so a group may contain other
groups. This method should *only* return users i.e. all contained groups
should be fully expanded.



---++ ObjectMethod *isGroup* <tt>($name) -> boolean</tt>

Establish if a $name refers to a group or not. If $name is not
a group name it will probably be a canonical user id, though that
should not be assumed.



---++ ObjectMethod *isInGroup* <tt>($cUID,$group) -> $boolean</tt>

Test if the user identified by $cUID is in the given group.



---++ ObjectMethod *eachMembership* <tt>($cUID) -> $iterator</tt>

Return an iterator over the groups that $cUID
is a member of.



---++ ObjectMethod *checkLogin* <tt>($login,$passwordU) -> $boolean</tt>

Finds if the password is valid for the given user. This method is
called using the login name rather than the $cUID so that it can be called
with a user who can be authenticated, but may not be mappable to a
cUID (yet).

Returns 1 on success, undef on failure.

TODO: add special check for BaseMapping admin user's login, and if
its there (and we're in sudo_context?) use that..



---++ ObjectMethod *setPassword* <tt>($cUID,$newPassU,$oldPassU) -> $boolean</tt>

If the $oldPassU matches matches the user's password, then it will
replace it with $newPassU.

If $oldPassU is not correct and not 1, will return 0.

If $oldPassU is 1, will force the change irrespective of
the existing password, adding the user if necessary.

Otherwise returns 1 on success, undef on failure.



---++ ObjectMethod *passwordError* <tt>() -> $string</tt>

Returns a string indicating the error that happened in the password handlers
TODO: these delayed error's should be replaced with Exceptions.

returns undef if no error



---++ ObjectMethod *removeUser* <tt>($cUID) -> $boolean</tt>

Delete the users entry. Removes the user from the password
manager and user mapping manager. Does *not* remove their personal
topics, which may still be linked.


@


1.4
log
@buildrelease
@
text
@d47 1
a47 1
   * wherever the code references $user, its a canonical_id
d49 1
d77 1
a77 2
---++ ObjectMethod *initialiseUser* <tt>($login) -> cUID</tt>

d79 3
d86 3
a88 1
Static function that returns a random password
d93 2
a94 1
   * =$login= - user login name. If =undef=, =$wikiname= will be used as the login name.
d114 1
a114 1
---++ StaticMethod *forceCUID* <tt>($cUID) -> $cUID</tt>
d116 4
a119 2
This function ensures that any cUID's are able to be used for rcs, and other internals
not capable of coping with user identifications that contain more than 7 bit ascii.
d121 2
a122 1
repeated calls must result in the same result (sorry, can't spell the word for it)so the '_' must not be re-encoded
a123 1
Please, call this function in any custom Usermapper to simplifyyour mapping code.
d126 1
d128 3
a130 1
---++ ObjectMethod *getCanonicalUserID* <tt>($login) -> $user</tt>
d132 1
a132 2
Works out the unique TWiki identifier for the user who logs in with the
given login. The canonical user ID is an alphanumeric string that is unique
d136 5
a140 1
returns undef if the user does not exist.
d160 1
a160 1
---++ ObjectMethod *getEmails* <tt>($user) -> @@emailAddress</tt>
d162 1
a162 1
If this is a user, return their email addresses. If it is a group,
d172 1
a172 1
---++ ObjectMethod *setEmails* <tt>($user,@@emails)</tt>
d188 1
a188 1
---++ ObjectMethod *isInList* <tt>($user,$list) -> $boolean</tt>
d190 1
a190 1
Return true if $user is in a list of user *wikinames* and group ids.
d192 1
a192 2
$list is a comma-separated wikiname and group list. The list may contain the
conventional web specifiers (which are ignored).
d196 1
a196 1
---++ ObjectMethod *getLoginName* <tt>($cUID) -> $string</tt>
d198 1
a198 1
Get the login name of a user.
d203 1
d206 1
a206 1
can return undef if the user is not in the mapping system
d211 1
a211 1
---++ ObjectMethod *webDotWikiName* <tt>($user) -> $webDotWiki</tt>
d224 1
a224 1
---++ ObjectMethod *eachUser* <tt>() -> $iterator</tt>
d242 1
a242 1
---++ ObjectMethod *eachGroup* <tt>() -> $iterator</tt>
d259 1
a259 8
---++ ObjectMethod *isGroup* <tt>($user) -> boolean</tt>

Establish if a user refers to a group or not.

The default implementation is to check if the wikiname of the user ends with
'Group'. Subclasses may override this behaviour to provide alternative
interpretations. The $TWiki::cfg{SuperAdminGroup} is recognized as a
group no matter what it's name is.
d261 3
a263 1
QUESTION: is the $user parameter here a string, or a canonical_id??
d267 1
a267 1
---++ ObjectMethod *isInGroup* <tt>($user,$group) -> $boolean</tt>
d269 1
a269 1
Test if user is in the given group.
d280 1
a280 1
---++ ObjectMethod *checkPassword* <tt>($userName,$passwordU) -> $boolean</tt>
d282 4
a285 1
Finds if the password is valid for the given user.
d289 2
a290 1
TODO: add special check for BaseMapping admin user's login, and if its there (and we're in sudo_context?) use that..
d294 1
a294 1
---++ ObjectMethod *setPassword* <tt>($user,$newPassU,$oldPassU) -> $boolean</tt>
d310 1
a310 1
returns a string indicating the error that happened in the password handlers
d317 1
a317 1
---++ ObjectMethod *removeUser* <tt>($user) -> $boolean</tt>
a323 27

---++ ObjectMethod *ASSERT_IS_CANONICAL_USER_ID* <tt>($user_id) -> $boolean</tt>

used for debugging to ensure we are actually passing a canonical_id

These ASSERTS have been disabled, as they have been made dangerous and misleading
due to the legacy cUID code



---++ ObjectMethod *ASSERT_IS_USER_LOGIN_ID* <tt>($user_login) -> $boolean</tt>

used for debugging to ensure we are actually passing a user login

These ASSERTS have been disabled, as they have been made dangerous and misleading
due to the legacy cUID code



---++ ObjectMethod *ASSERT_IS_USER_DISPLAY_NAME* <tt>($user_display) -> $boolean</tt>

used for debugging to ensure we are actually passing a user display_name (commonly a WikiWord Name)

These ASSERTS have been disabled, as they have been made dangerous and misleading
due to the legacy cUID code


@


1.3
log
@buildrelease
@
text
@d2 2
d5 44
a48 2
Singleton object that handles mapping of users to wikinames and
vice versa, and user authentication checking.
d53 3
a55 1
---++ ClassMethod *new* <tt>($session,$impl)</tt>
a56 1
Construct the user management object
d59 2
a61 1
---++ ObjectMethod *finish* <tt></tt>
a62 4
Complete processing after the client's HTTP request has been responded
to.
   1 breaking circular references to allow garbage collection in persistent
     environments
d64 1
d66 1
a67 1
---++ ObjectMethod *findUser* <tt>($name[,$wikiname][,$nocreate]) -> $userObject</tt>
a68 3
   * =$name= - login name or wiki name
   * =$wikiname= - optional, wikiname for created user
   * =$nocreate= - optional, disable creation of user object for user not found
d70 1
a70 4
Find the user object corresponding to =$name=, which may be either a
login name or a wiki name. If =$name= is found (either in the list
of login names or the list of wiki names) the corresponding
user object is returned. In this case =$wikiname= is ignored.
d72 1
a72 1
If they are not found, and =$nocreate= is true, then return undef.
a73 2
If =$nocreate= is false, then a user object is returned even if
the user is not known.
a74 2
If =$nocreate= is false, and no =$wikiname= is given, then the
=$name= is used for both login name and wiki name.
d76 60
a135 3
If nocreate is off, then a default user will be created with their wikiname
set the same as their login name. This user/wiki name pair can be overridden
by a later createUser call when the correct wikiname is known, if necessary.
d141 179
a319 2
Return a list of user objects for the users that have this email registered
with the password manager.
d321 1
d323 1
d325 2
a326 1
---++ ObjectMethod *createUser* <tt>($login,$wikiname) -> $userobject</tt>
a327 3
Create a user, and insert them in the maps (overwriting any current entry).
Use this instead of findUser when you want to be sure you are not going to
pick up any default user created by findUser. All parameters are required.
d330 1
d332 1
a332 1
---++ ObjectMethod *addUserToMapping* <tt>($user) -> $topicName</tt>
d334 2
a335 2
Add a user to the persistant mapping that maps from usernames to wikinames
and vice-versa.
@


1.2
log
@buildrelease
@
text
@d2 1
d10 1
d16 1
d49 7
d57 1
a69 18

---++ ObjectMethod *initializeRemoteUser* <tt>($remoteUser) -> $loginName</tt>

Return value: $remoteUser

Acts as a filter for $remoteUser.  If set, $remoteUser is filtered for
insecure characters and untainted.

If not user is passed, the remote user defaults to $cfg{DefaultUserLogin}
(usually 'guest').

If we got here via an authentication status failure, then the remote user
is set to blank, effectively signalling an illegal access.

If no remote user name was passed in, the user defaults to
$cfg{DefaultUserLogin}.


@


1.1
log
@buildrelease
@
text
@d13 8
d25 1
a25 1
   * =$nocreate= - optional, disable creation of user object for user not found in TWikiUsers
d28 1
a28 2
login name or a wiki name. The name is looked up in the
TWikiUsers topic. If =$name= is found (either in the list
d35 1
a35 1
the user is not listed in TWikiUsers.
d53 1
a53 1
---++ ObjectMethod *addUserToTWikiUsersTopic* <tt>($user) -> $topicName</tt>
d55 2
a56 3
Add a user to the TWikiUsers topic. This is a topic that
maps from usernames to wikinames. It is maintained by
Register.pm, or manually outside TWiki.
@
