• Do not register here on develop.twiki.org, login with your twiki.org account.
• Use View topic Item7848 for generic doc work for TWiki-6.1.1. Use View topic Item7851 for doc work on extensions that are not part of a release. More... Close
• Anything you create or change in standard webs (Main, TWiki, Sandbox etc) will be automatically reverted on every SVN update.
Does this site look broken?. Use the LitterTray web for test cases.

Item3838: Refactor users code for efficiency and clarity

Item Form Data

AppliesTo: Component: Priority: CurrentState: WaitingFor: TargetRelease ReleasedIn
Engine   Normal Closed   n/a  

Edit Form Data

Reported By:
Applies To:
Current State:
Waiting For:
Target Release:
Released In:


See TWiki:Codev.RefactorUsersCode and Item3256

-- TWiki:Main/CrawfordCurrie - 03 Apr 2007

First checkin just went in. Testing and benchmarking required!


Fine. At least the checkin 13257 mysteriously removed the fatal error in Fn_USERINFO.pm, which was the last to fail when I tried this afternoon.


The symptoms of Item3338 are here again (for which I fortunately had a test case). The reason might hit elsewhere, too: Plugins have, via Func, only access to the wiki names of users. They call TWiki::Func::wikiToUserName, which calls to $users->getLoginName, which in the current implementation is a NOP. Ooops.... I'm commiting this one.


Maybe for a similar reason I can't use the %COMMENT% field on develop? I get access denied, but can edit quite fine....


Yes, it is a similar reason. The CommentPlugin calls TWiki::Func::getWikiUserName(); which returns the wiki name with web prefix, whereas TWiki::Users::findUserByWikiName doesn't handle those.

This is tricky. I've found quite some plugins which call TWiki::Func::getWikiUserName(); for access control. Not all of them are bundled with the core, so expecting users to upgrade all of them is a no-no.

The correct fix should be to handle the occasional web prefix in the user mapping, since as MD pointed out elsewhere, alternate user mappings don't necessarily have a web prefix at all. But there are smells lurking:

  • The comment in TWiki::Users::findUserByWikiName says: "Return a list of users for the users that have this wikiname. Since a single wikiname might be used by multiple login ids, we need a list.". This is insane. Plugins have no access to the well-defined login name of the current user, so they can only pass on the wiki name - only to find out that, well, "it may be any of these". How should TWiki authors reliably specify access control settings if there can be lists of users behind one wikiname? Or is it intended to allow multiple login methods to be used in parallel, so that the same user can show up with a different syntax of login ids?
  • TWiki::Users::TWikiUserMapping::findUserByWikiName silently assumes that the conversion hashes have been loaded in advance. If a user isn't found, it returns an empty list, the first element of this list is undef.
  • Which routine in the calling sequence is in charge of removing stuff like %MAINWEB%. or Main. if given in an access control list of TWikiUserMapping installations? I couldn't spot any (but have not yet tested).


TWiki:Main.SvenDowideit pointed out yesterday that many login names may map to a single wikiname - and there are indeed places where this happens. The wikiname is just a display artifact and cannot be assumed to be unique. So I started reading the code in detail, and I believe that this was indeed the original (pre-Cairo, undocumented) intent. Rather than ignoring the problem and hoping it would go away (which it won't), I decided to bite the bullet and recode the core to at least allow this many to one mapping to exist. That's why finduserByWikiName returns a list. I tried as much as possible to remove the smells from the core, but unfortunately this of course concentrates the whiff in the TWiki::Func API.

In TWiki, access controls are specified using wikinames, which means the process of passing getWikiUserName to checkAccessPermission is correct. The Func API shouldn't work any differently to before. Internally, the wikiname has to be mapped to a login name. This is unfortunate, but unavoidable, because groups are defined by the user mapping manager in terms of login names, not wiki names, so access control lists have to be expanded out to login name lists.

Plugins have no access to the well-defined login name of the current user - as long as the mapping is 1:1, then they can always wikiToUserName(getWikiUserName()). If the mapping is 1:many, then true; this is one of the problems inherent in the Func API. but then again, why do you want the login name?


I agree that Plugins should not use the login name. All they need is a documented way to do correct access control. But nevertheless: The wikiname is just a display artifact: No, that's not true. The wikiname must be the common denominator for all conceivable user mappings, and conceivable login managers, all conceivable store backends, and whatever "pluggable" stuff we have.

  • The wikiname is used as RCS user. Login names can have a syntax which is not compatible with RCS - as we have seen in the past.
    • The canonical user id is stored there, which happens to be the login name but could be the wikiname at the flick of a switch (theoretically, of course), or any other filtered string.
      • It is the login name since r13257. At some day in the past it has been deliberately changed from login name to wikiname because of unpredictable problems with login name syntax. Every new login mechanism could break existing filters, but not if we stick to wikinames. -- HJ
  • Currently (r13258) the login name is stored in the lease file. If the login manager has user ids like ia005692 then the output of the lease conflict page is pretty useless.
    • See previous answer
  • It can even be plain wrong, if there are lists of login names because, when in doubt, the first login name is taken. What if the second login name is actually editing?
    • See previous answer
  • It is the wikiname which appears in the log files.
    • See previous answer
  • In access control, wikinames are documented user interface, not just "display artifact".
    • Agreed.
The only thing which is a "display artifact" is the web prefix which makes the wiki name autolinkable from every TWiki topic. For alternate user mappings which do not have a users web I'd rather dare to let them set their $TWiki::cfg{UsersWebName} to whatever prefix they like, say 'Main.MyLdapUserRetriever?wikiname=' than to try to map everything to login names.

For access control, the definition of access control is done in terms of TWiki groups and wikinames, and every request has its unique wikiname associated with it. Mapping both in a 1:n way to login names is just a superfluous complexity. Maybe some particular user mapping can only expand groups based on login names - but then, the code to do so should be shoved to that user mapping module and not enforced on the core.

Drats. And once again I've been bitten by the fact that CommentPlugin is broken.


sigh I can't win on this one. Rather than trying to patch up the assumptions piecemeal, here are the choices:

  1. Normalise on a 1:1 login-name -> wikiname mapping, and change to using the wikiname everywhere. That's where I was before Sven spoke up.
    • thus while N logins can log in as a single wikiname, there is no distinction between them once they have done so
    • user mapping engines must take responsibility for expanding groups to lists of wikinames instead of lists of login IDs (this is probably the single hardest thing to do...)
    • the login name would only be used for password checking, nothing else
  2. Agree that the login name is "more unique" and only apply the mapping to a wikiname where a user name has to be displayed. The major impact here would be on the TWiki::Func interface, which as you point out above uses wikinames.

I think that Sven, you, and I should agree on how to do this, as a wider debate would just get bogged down (though comments are welcome).

For the record at this point I agree with you that 1 is the way to go. We may need to remove the group membership iterators if a user mapping manager can't reverse the mapping from a user ID to a wikiname.



There are 2 root effects that we can strive for.

  1. TWiki User names, as displayed (ie the WikiName) is the most important thing in an organisations identification system.
  2. TWiki Usernames, as displayed are derived from an organisations existing identity and authorisation system.

I posit that 2 is the more reasonable (wrt adoption, and acceptance), and that it is normal in a large enough group to have 2 JohnSmith's both of whom quite reasonably expect to be displayed as JohnSmith.

The other, less social reason, is that for distributed identity and auth systems (OpenID being the most obvious) there is only one guaranteed unique thing - the login-name. All other informations (Firstname, Lastname etc) are set from a non-authoritative, personal perspective.

Same issues exist in bigger corporations.

So, I'm trying to get TWiki into a state where it will be transparently integratable into the existing systems, rather than be 'yet another identity'

To this end, it becomes necessary to not only separate login (the unique thing) from the display, but also from the user's home topic, if they / their admins choose to have one.

If TWiki goes to the less flexible route of insisting that the WikiName is unique, and must be a TWiki topic, then there are user groups out there that we cannot support - those that want to integrate a TWiki to add to their existing systems (most do not want yet another registration system, nor to manage TWikiUser groups).

-- TWiki:Main.SvenDowideit - 04 Apr 2007

It seems that we are getting clearer...

Yes, I opt for using the wikiname inside the core, as initially proposed by Michael Daum in the Codev topic. The TWiki core needs a simple, well documented syntax and semantics for their view of a "user" on which all extensions can reliably build. There is no point in having a distinction between different login names using the same wikiname because the users can't make any use of this distinction.

A user mapping manager does not necessarily need a mapping from wikiname to login name. But all of them need a way to map the initial login name to the wikiname for every request. So mapping a login name to a wiki name can't really be "the single hardest thing to do", whereas the opposite direction can't be done reliably at all if you have different people calling themselves JohnSmith.

Requiring unique wikinames does not imply that there must be a TWiki topic for the users, the engine doesn't need them. You can integrate a TWiki to existing systems without another registration system, and there is no need to manage TWiki user groups. Strictly spoken, using wikinames internally doesn't even mean that they need to be unique.

Our organisation is big enough to have more than one FirstnameLastname, but I strictly require that they both register with different wikinames (to be precise: I'm disambiguating them with automatic registration from LDAP). I can not imagine a corporate setup which would be sloppy in that respect.


While you may have the luxury of insisting that users have unique First&Last, ...

  • As I wrote above, I have more than one user with the same first and last name, and I am disambiguating using other LDAP attributes. -- HJ

...I have come across many places that do not have this ability. In fact, I just read a comment in the LDAPContribDev topic that is another example of this.

  • The most recent comment in TWiki:Plugins.LdapContribDev by Stephane Lenclud is talking about duplicate logins against independent LDAP servers, not about duplicate wikinames. -- HJ

OpenID has no central authority to set Display names.

  • I admit that I don't care for OpenID. -- HJ

But the Core of my argument is this:

Using LoginName as the unique identifier provides TWiki with much more flexibility with regard to compatibility with other organisations setups, choices and processes, as it does not exclude DisplayNames from being unique. On the other hand, limiting TWiki to needing both login name and displayname to be unique, already excludes some of my clients, and forces other organisations to adopt a multiple Identity structure, or to choose some other Wiki engine.

  • As I wrote above, from a technical point of view display names need not to be unique. Stephane, in TWiki:Plugins.LdapContribDev, wants unique user topics even for the same login names if these are validated by different servers. -- HJ

-- SvenDowideit - 04 Apr 2007

Well, I'm going to sit on the fence a while longer to see if either of you gives way. I can see the arguments on both sides. Architecturally Sven is right

  • login names are the corporate identity key
    • Only if you don't have a directory, but most companies have. In Windows setups, most admins would see the DN (distinguished name) in Active Directory as the identity key. Login names don't reach further than your single signon domain can carry. -- HJ
  • login names will be used by any external ACL provider (when we get to that)
    • I beg to differ on that one. For external access control we are using X.509 certificates. There's a 1:1 relationship between internal login names and X.509 certificates issued for our company. -- HJ
  • sysadmins expect login names to be the "unique bit" - most see wikinames as simply a mashup of fname.sname, so are surprised when they have to be unique
But it creates coding issues such as those pointed out by Harald above that I would rather avoid. IME all my clients have a way of extracting a unique wiki name for each user, either through automatic registration or through some manual process. But these processes are a pain to set up. We shouldn't let the fact that ACLs and TWiki groups - even the Func API - are currently defined in terms of wikinames cloud our judgment. Please also ignore the fact that there are some systemic problems with my current approach of equivalencing the login name and the canonical user id. That can be fixed easily enough.

I am prepared to put the work in to "get this right" but I do not want to walk away leaving a mashed-up compromise.


I am close to giving up on this one. I'm all yours if as long as replacing the User object with a scalar is concerned. But I find it really annoying if plain TWiki has to go through extra loops to accomodate for some external "pluggable" mapper. It is still unclear to me what benefit would come from some extra definition of "canonical user id" different from the wikiname, be it unique or not.


Good discussions here. Could we move this spec discussion over to the Codev web?

For the records, up to Cairo, the login name was the unique name that has stored in TWiki (RCS etc.), only the signatures and groups were done as WikiNames. TWiki 4 changed that. For compatibility, be carful if you change this again.


Peter, no, the ACLs were also done as wikinames. My intent in TWiki 4 was that it shouldn't change anything other than to add a user object, that allowed us access to both identities in all places. I see now by reviewing the logs that I did indeed change the RCS identity from the login name to the wiki name. The change was not intentional; I just misread the undocumented code.

Right now, plain TWiki does not go through any extra loops to accommodate an external mapper. The mapping code has just been abstracted to a separate module so it can be replaced, but is otherwise almost identical to what was there before the mappers came into existence.

Harald, "canonical user id" is just terminology - it is simply an abstraction to try and help coders avoid getting bogged down in this very discussion. As far as the core code is concerned, all it needs is a unique "handle" for every user. Whether that is a login name, a wiki name, or a type of sausage, is irrelevant as long as all ID requests go through the Users module, as I documented.

As Peter has pointed out, the login name was used in earlier versions of TWiki, though of course those versions shared the problems with ACLs and groups. Right now I'm having difficulty seeing a counter argument that would make me recode TWiki to use wikinames instead of login names as the scalar that identifies users. I've been very close to this code over the last few days, and I can assure you it doesn't get any simpler if you do!

However this still leaves us with an issue, and that's the problem that Harald highlights. A login ID may contain characters that are illegal in some contexts (e.g. in an RCS user identity, or in one of the many status files where user ids are stored. So here's what I'm going to do unless someone else has a better idea: code a mapping from a login ID to a canonical user id that does not have any such issues. This scalar can be fed to the Users module to recover either the wikiname or the login name, and is the name that will be used in (for example) RCS histories. For systems where the login name is alphanumeric, this name will be the same as the login name. I need to work out some test cases for this; real world examples of login names (e.g. those used in windows domains) would be most helpful.

Any final comments?


Please move this discussion to the Codev web.


This aspect of the discussion is closed now, but we do need to discuss how to expose users to plugins authors so I started TWiki:Codev.UserIdentifiersInPlugins

Any yawning chasms will no doubt be opened up there.


I think these code changes are stable enough now to be able to close this. We still need at least one implementation of a user mapper other than the standard to check out the API for cleanliness.


Summary Refactor users code for efficiency and clarity
ReportedBy TWiki:Main.CrawfordCurrie

SVN Range TWiki-4.1.2, Mon, 26 Mar 2007, build 13227
AppliesTo Engine

Priority Normal
CurrentState Closed

Checkins TWikirev:13257 TWikirev:13258 TWikirev:13263 TWikirev:13270 TWikirev:13278 TWikirev:13280 TWikirev:13291 TWikirev:13299 TWikirev:13364
TargetRelease n/a

Edit | Attach | Watch | Print version | History: r29 < r28 < r27 < r26 < r25 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r29 - 2007-04-13 - CrawfordCurrie
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback