There has been various discussions in the past about different aspects of the Foswiki registration process, and how it can be improved. This topic is an attempt to pull these threads together, and create a plan for giving Foswiki a pluggable registration process. Please feel free to edit it.
Overview
User management is performed by four components; the LoginManager, the PasswordManager, the UserMappingManager, and
UI/Register.pm
. Their responsibilities divide up as follows:
- PasswordManager manages user passwords and other secret data; add, delete, check user passwords and email addresses. You can plug in different password managers.
- LoginManager handles the login process; generates screens for login, sets up logged-in user context. You can plug in different login managers.
- UserMappingManager fulfills two duties:
- it maintains a tridirectional mapping between username, display name (wiki name) and canonical user id. You can plug in different user mapping managers (in fact this is the main mechanism for integration with external auth providers)
- it maintains membership of users to groups
- UI/Register.pm does everything for registering a new user, all tangled up together and assuming UserMappingManager == TopicUserMappingManager i.e. that users and groups are stored in topics. The first three of these components each has an abstract base class and a set of derived classes, one for each implementation.
Note that "users are stored in topics" is
not the same as "users have personal topics". Any registration process may result in the creation of a user topic. Some user mapping managers may infer semantics from the fact that a user topic exists; other will not. Some user mapping managers may use topics to store user databases (e.g
WikiUsers); others will not.
- Users may have personal topics in the %USERSWEB% - but this should not be assumed
- User mapping managers may use topics to store additional user information - but fast ones won't So, the generic registration code has to be independent of the existence of topics, and the fact that the user database is stored in a topic should be hidden by the user mapping manager. However the management of personal topics is a generic requirement and services to do this should be provided.
Code flow
Registration works like this:
- User visits a "Registration" page and enters their details
- Submitted page is used to generate a "partial registration". In fact the registration details are partly written to the other handlers, and partly cached in a record for verification
- Verification confirmation is requested
- User verifies
- Cached information is used to complete registration of the new user
At the moment the limit of programmability is skipping steps 3 and 4, and switching on/off login names.
At a high level this flow works for every registration process I can think of. Here are some considerations that may affect the flow:
- Registration approval - step between 2 and 3 where the registration request is submitted to someone else for approval
- Post registration steps, such as adding user to groups
- Self-modification of registration information - login name, wiki name, password, verification codes etc.
Requested features
Various features have been requested for registration. These need to be borne in mind.
Pluggable versus Plugin handlers
Some commentators have asked that we add plugin handlers to address things like registration. I am against this approach for several reasons:
- Plugins add overhead
- Plugins are intended to be swapped in and out without breaking the system (ideally)
- It is hard to predict all the places where a registration provider would need to interact. We would end up providing handlers at every step of registration.
It's much better to use a pluggable module approach, as used for the login manager etc. That allows an implementor to subclass any aspect of the registration process without the overhead - or call complexity - of a plugin.
Conclusions
We should view registration as an "information gathering" process. This process starts with the user entering basic information required for registration, and proceeds through an arbitrary number of intermediate steps where additional information is gathered - for example, registration approval, user verification, permissions from group owners to add the user to their groups. The user should not be registered with any other subsystem until this information is complete and verified. The current registration configuration options - allow login name, and skipping verification, should as far as possible be replaced by subclassing and/or mixins.
Note that the registration process described above is a workflow. There may be opportunities to leverage existing workflow implementations, such as
WorkflowPlugin.
The existing registration code goes some way to defining a "user record" that contains all the information associated with a registration. However this needs to be cleaned up, formalised and documented. Fields in this record should be marked as "temporary" (for the registration process) or "permanent". The record could then be used to communicate with the user mapping code, which would decide how to handle the registered user. I think that interactions with the password manager should also be moved to the user mapping manager.
Registration doesn't stop when the user is authorised to edit the wiki. The registration record should be retained by the registration module, and made available for subsequent queries - USERINFO, for example. The user record may be enhanced subsequently, for example with photographs, biographies and genetic profiling results. This suggests that the record may comprise two parts - a public part, in a "personal topic", and a private part, held in secure storage by the registration module (e.g. in LDAP). Either part should support addition of arbitrary information, as defined by form specifications local to the installed wiki.
The PasswordManager and LoginMananger modules have fairly well defined responsibilities - I doubt that there is much more to add to them. That leaves us with two logical places where registration code might go:
UI/Register.pm
(which should become the generic registration interaction module),
Users/TopicUserMappingManager
(which should take code that assumes users are stored in topics).
--
CrawfordCurrie - 21 Jun 2009
When redesigning the UserMapping code, it might be worth separating the group membership code from mapping user
ids. The two functions - added a note above - are somewhat blended in for no obvious reason. Sorry if offtopic
--
MichaelDaum - 22 Jun 2009
An interesting point, but I didn't propose redesigning the user mapping code, and don't think that should be included in the scope of this work.
--
CrawfordCurrie - 23 Jun 2009
I would like to bump this discussion with respect to
security. How about using a
CAPTCHA based registration process in order to prevent bot/script based wiki spammers from messing with a public Foswiki installation?
There is perl implementation for reCAPTCHA available:
libcaptcha-recaptcha-perl - perl implementation of the reCAPTCHA API.
However, this could add to installation dependencies.
--
MatthiasWientapper - 20 Dec 2009
reCAPTCHA could be added to the CPAN dir in lib.
--
ArthurClemens - 20 Dec 2009