On Fri, 2008-10-31 at 17:33 +0200, Timo Sirainen wrote:
What I'm worrying here is if all users have shared something. For example how does this work with global ACLs? IIRC if there's a global ACL for e.g. "Spam", Dovecot will create dovecot-acl-list with "Spam" in it for all users. Even without global ACLs the number of users sharing something might be a bit too large.
So the performance would be a lot better if the dict stored something like source_user -> dest, where dest would be all the user names and group names that are included in the user's ACLs (for any mailbox). Then you'd look only at those users' mailboxes where you or your groups are mentioned. Negative user/group rules perhaps shouldn't be in the dict.
Maybe something like:
Dict contains /acl/$dest/$source_user -> 1 where $dest is either the ACL user or ACL group (with u= and g= prefixes so they don't get mixed) and $source_user is the user whose mailbox ACL is being changed.
This allows getting a list of all possible users whose shared mailboxes we have visible. Just do a dict iteration for /acl/$user and /acl/$group for each group we belong to. And I guess also check /acl/anyone and /acl/authenticated.
As for updating the dict, it should normally be done by acl_backend_vfile_object_update(). It should also immediately update the dovecot-acl-list file. This should take care of all the ACL changes that are done via IMAP. The dict changes are single entry updates or deletions, no iterations, so the IMAP ACL commands are relatively cheap to use.
Changing dovecot-acl files by hand then requires dropping removed users/groups from the dict. Since we don't know anymore what was removed, we have to go through the entire dict and find all the entries with /acl/*/$source_user. Then add the missing entries and delete the unnecessary entries. Triggering this rescan could be done by acl_backend_vfile_acllist_verify() when it's also rebuilding the dovecot-acl-list file.
Then there's a final problem of how to rebuild the dict in case it gets broken, desynced or whatever. I think this would be solved most easily with an increasing acl-validity value (UNIX timestamp). In dict store it to /acl/validity and in each dovecot-acl-list store it to its header (which doesn't exist yet, need to add it). When reading or updating dovecot-acl-list file check if its acl-validity value is different from dict's /acl/validity value. If it is, trigger a dictionary rescan.
I think it should rescan only the one user whose dovecot-acl-list is being read (so the code would be identical to handling changed dovecot-acl files), because it might take too long to rescan all users' ACL files. This means anyway that deleting everything from dictionary would cause shared mailboxes to be lost from LIST until either the dovecot-acl-list is being read by either a) the owning user logging in and issuing a LIST command, b) the destination users having those mailboxes subscribed and issuing a LSUB command.
Any hope of getting you to implement at least parts of this? :) Also the IMAP ACL code needs to be moved to a separate imap-acl plugin. After those two I could start trying to get all of it merged.