We add the following cards:
Each setting value is a special type of pointer*. Stored as list of multiple items, each of which can be
Note: "_left" is a special case that cannot be used in combination with other values. This drastically simplifies implementation issues.
*Design question: how does this interface work? special cardtype? special *input? Obviously, we don't want users having to type "_left" or "_creator". Needs to be some sort of dropdown. More on this later... Also, what is the value for comment = nobody?
Zero, or whatever will make it possible to use logic like "if foo+*comment then...".
In order to cover the existing permissions in relatively few settings, we need the following new sets (each of which requires its own new set class)
I think this is the new hierarchy: *all, *plusses, *stars, *type.. The relative placement of the new two doesn't matter much, since they're mutually exclusive.
We may want to think more about the name for the set classes. One the one hand, both *plusses and *plus cards are already in use. On the other hand, they're both one-set cards like *all, and the simple cards aren't really in use now as anything but placeholders.
As part of this upgrade, we can get rid of the roles extension and the special handling for roles/users.
Basically, I think a Role (henceforth a "Group") should basically just be a pointer. Whoever has permissions to edit the role basically has permissions to manage the group (which gets rid of one more global permission. see below).
Design issue: Editing the role directly is then straightforward. The question is how best to edit it from the users' cards. This is basically a matter of managing the pointer from the pointee. There are lots of use cases for this, and there is some infrastructure in place already. But this particular example needs to work really well, of course.
(John, I know you're going to say "Group" is too common of a name to grab. I resent that, because it's true. Let's talk).
For performance reasons, the card containing reader setting values will be optimized in the database as a "read_rule_id".
For any user, we need to come up with a list of all read_rule_ids that include that user.
So now this is straightforward. You just substitute the current reader_id stuff with something similar -- cards where the read_rule_id is in the user's read_rule_ids list
Whenever you add, remove, or rename a setting value, you need to update impacted cards.
( Old terminology. Still useful?) Note that if the setting value is _left, the rsvid is the rsvid of the left card, not the card with the content "_left". Lew's pseudo code for this one:
card.reader_setting_value_id = follow_parent( c.setting(:read) ).card_id
The rsvid may need to be updated when:
In case #3 above, what we do is first find all the distinct rule_ids for all the cards in the set of the new setting value. Then we examine those rule_ids and update only the ones whose old values are more general than the new one.
In case #4, we follow something very much like the logic of #1, but we also need to update all the old cards.
1. migrate roles into cards (leaving the old roles in tact for now). If the role card has some special content, then....what?
2. migrate in the new set and setting cards
3. migrate permissions (setting values). for each permission, follow this pattern:
4. Re-implement initial permissions in cards on en
5. get rid of the old permissions and roles tables. (Don't actually implement this until the others are proven)
We could also treat this as an opportunity to get one step closer to getting rid of our global permissioning system. As I see it, the only thing that needs to happen to get rid of it altogether is moving user information into cards.
These two will now be unnecessary (and, actually, way way improved) thanks to the current refactor: