Groups are tied to a specific channel, but can also be inherited by subchannels, when the flag "Inheritable" is set in the parent channel and "Inherit" is set in the subchannel (usually you want these flags to be set). This opens a convenient way to administer channels and their ACLs; set up the ACLs on the top of the channel tree that should have a similar privilege structure, and just change the group memberships on subchannels.
For each channel, a group has 3 pieces of data:
1. "Members": the list of players to add to the group (i.e. because they are not members of the same group in the parent channel already),
2. "Inherited members": the list of members inherited from the same group in the parent channel and
3. "Excluded members": the list of inherited members to remove from the group.
Note: Only registered players can be added to groups.
Let's take a practical example, the admin group. Every time a player makes a channel, he is automatically added to its admin group. This doesn't automatically give him any privileges, it just marks him as a member of that group, however Murmur's default installation installs an ACL that grants the admin group the Write ACL (all access) permission.
In a structure like this:
player "Big Boss" is the only Member of the admin group in Root. In channel A, player "BossA" and in channel B, "BossB" are added to the Members of admin,
In the channels Root, A and B the flags Inherit and Inheritable are set for the admin group (default setting in Murmur). A player being a member of that group in any of these channels thus is an inherited member in a subchannel. So the total list of members in channel B is "Big Boss, BossA, BossB". The convenience of this system is that if we later add "Super Boss" to admin in Root, he'll automatically be in the admin group of the channels A and B.
Let's move on, and say that player "BossC" is in the Members list in channel C, but here admin is not marked as inherit. This means that "Big Boss" is not in the admin group and any changes for admin in Root will not be seen here. Channel D will inherit the list from C, unless C also marks admin as not inheritable.
ACL (Access Control Lists) are all attached to a specific channel. A channel can specify if it wants to inherit the ACL on the parent, but it cannot specify which; it's a all or nothing deal. ACL are evaluated in order, from top to bottom along the chain of channels. To add or remove an ACL, right click on the channel you wish to change ACL's on and click "Edit ACL." Once you add an ACL, you set the group the ACL defines by typing it's name in the bottom left box labeled "Group." If you just want to set an ACL for a specific user, leave the Group box blank and type the name of the user in the box labeled "User ID."
For each entry, either a user or a group will match. A user must be a specific, registered user, while a group can be any group valid in the channel the ACL is defined on. Note that group membership is evaluated in the channel the ACL is executed in, which is important for inherited ACLs. If a group begins with a !, it's membership is inverted, and if it begins with a ~, it is evaluated in the context of the channel the ACL is defined on (and not the active channel).
All authenticated users
All users inside current channel
All users outside current channel
For each entry, permissions are either allowed or denied; in case of a conflict the last entry takes precedence. Remember that all entries are evaluated in order, so if you have the following set of entries:
- @all deny speak
- @all allow speak
Then everyone will be allowed to speak. On the other hand
- @all allow speak
- @all deny speak
Will deny speak from everyone.
Each entry can be marked as either applying in the current channel, in subchannels or both. Most of the time you want both. Remember that for an entry to be applied on a subchannel, you have to apply it to subchannels and allow inheritance in the subchannels.
The @sub group
There is a special group called sub, which just like all has a special meaning. Sub is used as sub,a,b,c, where a is the minimum number of common parents, and b and c restrain the path depth:
- b is the minimum and c the maximum path length, measured from the channel referred by a.
- If any of those parameter is missing, then there will be no minimum/maximum path length.
It's somewhat complex, but also rather powerful. For example, assume the following tree:
Let's deny enter to all on Root to start with. Then, on A, we define
- @~sub,0,1 +enter
First of all, this ACL will be evaluated in the context of the defining channel, since the group starts with ~.
The first parameter (0) indicates how many additional elements of the path name must match. A zero means we require a match up to this point. This means that any player in a channel under the path Root.A will match (so in all sub-channels).
If this first parameter had been 1 the evaluation would start one level below Root.A, where the ACL was defined. The second parameter with value 1 indicates all sub-channels (thus now of Root.A.*) are allowed to enter. So we would be allowed to enter Sub1 and Sub2.
Setting this to positive values only makes sense for pinned groups (with the ~).
The second parameter requires the path of the evaluated channel to be at least one element longer than the path of the channel of the ACL. So this rule will match in anything that starts with Root.A and has at least one more element.
To sum it up; this rule allows anyone in one of A's descendants (but no A itself) to join A or any of its descendants (we assume subchannels inherit the rule).
If we don't use the ~, then it will allow people in any of A descendants to go up (ie, from Sub1 to A1 or A but not the other way) or, in other words, allow people in the descendant of a channel (any depth) to enter it.
Let's add a new rule to A1:
- @sub,-1,0 +link
This allows anyone that's in the parent (equal path up to -1 elements (the first parameter)) or any of the siblings (path length equal (the 0 parameter)) to link to this channel.
And finally, just to show how messed up it can get, let's add this on B:
- @~sub,-1,2,2 +enter
This lets anyone that's currently in a descendant of Root (B's parent) and has a path length of exactly 2 (length of Root.B -1 + 2) join, so this rule would match someone in A1, but not A or Sub1