> > |
%META:TOPICINFO{author="VitoMiliano" date="1077874140" format="1.0" version="1.1"}%
- TWiki already has users and groups, we just don't take advantage of them much right now. Users are regular usernames, which we use on a per-company or per-project basis. Groups are names that end in Group, e.g. SpecialGroup? which has a list of all the users allowed to access the Special web; we only use this for per-web access control. Groups can also have other groups in them, so you could have SomeUsername?, who is part of ProjectGroup?, which is part of CompanyGroup?, etc.
- TWiki already has web- and topic-based access control, it just isn't supported uniformly. In a topic's text, you can do something like:
* Set DENYTOPICVIEW = YourName?, MySelf?, ThatOtherGuy?
and everyone but you, me and that other guy will be able to read that page. However, there are lots of ways to work around that restriction, because TWiki sucks. Also, it means that what should be metadata, like the document summaries and changelogs, is in the topic text, not the TWikiForm? metadata, which we've determined is bad. Otherwise, it's fine, because there are variables that let you either deny or allow both viewing and editing, and both users and groups are seamlessly supported.
- The biggest way to work around that restriction is to do a specially-designed search, because search uses grep or bool, independent of anything TWiki, so it returns all the search results at once, without any filtering. So to filter the results for these restrictions, you have to open each result, read the file for the restrictions, recursively parse the names to see if you're in there (remember, you can have groups within groups), and then add that to your new list of cleared pages to display. Needless to say, on a big search, this will be slow as ass.
- The much-maligned staticexport script had to solve this problem already, because we have to do the same thing to see if any topics have been updated. There's no way to get the revision information except by loading up the topic and checking it. So what we do, is when the topic is saved, we write out the topic name and the revision number to an external database file so we can check it real fast later.
- Therefore, I believe that the Correct way to solve this problem is to perform the following:
- Perform a security audit on TWiki. Find every place where a topic gets loaded and wrap it in a stub security checking function.
- Move the topic-specific access controls into metadata. Create a new variable in TWikiPreferences? (one that can be overridden in WebPreferences, unless it's set as FINALPREFERENCES, as a normal TWikiPreferences? variable can be) called, perhaps, ACCESSCONTROLFORM that has the name of a TWikiForm? which has the six topic-specific access control variables in it (ALLOWTOPICVIEW and DENYTOPICVIEW, ALLOWTOPICCHANGE and DENYTOPICCHANGE, and ALLOWTOPICRENAME and DENYTOPICRENAME). This TWikiForm? can be our existing ClassificationForm?, or can be a new AccessControlForm?, it doesn't matter, because topics can have multiple TWikiForms?.
- Generalize the metadata databasing code from staticexport into a generic module, perhaps one that, on topic save, writes out ALL the TWiki metadata into a database, not just name and revision information, but all of it plus the contents of any TWikiForms?, and in the case of an access control form, include a completely expanded version of it (with all the groups and groups-of-groups broken down into the unique usernames they contain), for each topic.
- Edit your security function to check this database for the current username's presence (or lack thereof, in the case of DENY*).
- For proper rollout, integrate proper checking into "view" on every page view. If TWikiGuest? isn't allowed to view the page, authentication must occur; for us, this means supporting a separate URL (https://), which might be troublesome, because TWiki stores the base URL for the site (http://udn.epicgames.com) including the protocol; changing the base URL like that would break things. A possible solution might be breaking that variable into two, one for the protocol, one for the domain, and having a separate $authenticationProtocol and $authenticationDomain; if they exist, use them for authentication, if not, don't. I'll have to think more on this.
The other big issue is attachment viewing, but that's kinda outside
TWiki's scope, since you don't really want to route every file through
a viewing script. Although you could. That would be easy enough to
do.
If you're considering this to be an Apache-related task, then the
smart, Apache-using solution to do would be, on save, to distill the
same expanded username list into a new .htaccess file. Remember,
Apache uses ALLOW and DENY just like TWiki, and you've already got all
the users in a known .htpasswd. So after you distill the usernames,
insert them into your database, and write them out into your one-line
.htaccess file in that topic's "pub" directory, and poof, unified
attachment access control. |