Browse Source

properly implement ACL handling

Natenom/support-murmur-13-1446181288462
Michael Ziegler 15 years ago
parent
commit
368c137a61
  1. 45
      pyweb/mumble/MumbleCtlDbus.py
  2. 123
      pyweb/mumble/MumbleCtlIce.py
  3. 2
      pyweb/mumble/mctl.py
  4. 90
      pyweb/mumble/mmobjects.py
  5. 29
      pyweb/mumble/models.py

45
pyweb/mumble/MumbleCtlDbus.py

@ -135,10 +135,47 @@ class MumbleCtlDbus_118(MumbleCtlBase):
return MumbleCtlDbus_118.convertDbusTypeToNative(self._getDbusServerObject(srvid).getRegisteredPlayers( filter ) ) return MumbleCtlDbus_118.convertDbusTypeToNative(self._getDbusServerObject(srvid).getRegisteredPlayers( filter ) )
def getACL(self, srvid, channelid): def getACL(self, srvid, channelid):
return MumbleCtlDbus_118.convertDbusTypeToNative(self._getDbusServerObject(srvid).getACL(channelid))
def setACL(self, srvid, acl):
self._getDbusServerObject(srvid).setACL(*acl.pack())
raw_acls, raw_groups, raw_inherit = self._getDbusServerObject(srvid).getACL(channelid)
acls = [ ObjectInfo(
applyHere = bool(rule[0]),
applySubs = bool(rule[1]),
inherited = bool(rule[2]),
userid = int(rule[3]),
group = str(rule[4]),
allow = int(rule[5]),
deny = int(rule[6]),
)
for rule in raw_acls
];
groups = [ ObjectInfo(
name = str(group[0]),
inherited = bool(group[1]),
inherit = bool(group[2]),
inheritable = bool(group[3]),
add = [ int(usrid) for usrid in group[4] ],
remove = [ int(usrid) for usrid in group[5] ],
members = [ int(usrid) for usrid in group[6] ],
)
for group in raw_groups
];
return acls, groups, bool(raw_inherit);
def setACL(self, srvid, channelid, acls, groups, inherit):
# Pack acl ObjectInfo into a tuple and send that over dbus
dbus_acls = [
( rule.applyHere, rule.applySubs, rule.inherited, rule.userid, rule.group, rule.allow, rule.deny )
for rule in acls
];
dbus_groups = [
( group.name, group.inherited, group.inherit, group.inheritable, group.add, group.remove, group.members )
for group in groups
];
return self._getDbusServerObject(srvid).setACL( channelid, dbus_acls, dbus_groups, inherit );
def getBootedServers(self): def getBootedServers(self):
return MumbleCtlDbus_118.convertDbusTypeToNative(self.meta.getBootedServers()) return MumbleCtlDbus_118.convertDbusTypeToNative(self.meta.getBootedServers())

123
pyweb/mumble/MumbleCtlIce.py

@ -195,54 +195,41 @@ class MumbleCtlIce_118(MumbleCtlBase):
@protectDjangoErrPage @protectDjangoErrPage
def getACL(self, srvid, channelid): def getACL(self, srvid, channelid):
import Murmur
acls = self._getIceServerObject(srvid).getACL(channelid)
ret = []
for x in acls:
if isinstance(x, list):
tmp = []
for y in x:
if y.__class__ is Murmur.ACL:
tmp.append([y.applyHere, y.applySubs, y.inherited, y.playerid, self.setUnicodeFlag(y.group), y.allow, y.deny])
elif y.__class__ is Murmur.Group:
tmp.append([self.setUnicodeFlag(y.name), y.inherited, y.inherit, y.inheritable, y.add, y.remove, y.members])
ret.append(tmp)
else:
ret.append(x)
# need to convert acls to say "userid" instead of "playerid". meh.
raw_acls, raw_groups, raw_inherit = self._getIceServerObject(srvid).getACL(channelid)
return ret
acls = [ ObjectInfo(
applyHere = rule.applyHere,
applySubs = rule.applySubs,
inherited = rule.inherited,
userid = rule.playerid,
group = rule.group,
allow = rule.allow,
deny = rule.deny,
)
for rule in raw_acls
];
return acls, raw_groups, raw_inherit;
@protectDjangoErrPage @protectDjangoErrPage
def setACL(self, srvid, acl):
def setACL(self, srvid, channelid, acls, groups, inherit):
import Murmur import Murmur
newacls = [];
newgroups = [];
for curr_acl in acl.acls:
new_acl = Murmur.ACL();
new_acl.applyHere = curr_acl['applyHere'];
new_acl.applySubs = curr_acl['applySubs'];
new_acl.inherited = curr_acl['inherited'];
new_acl.playerid = curr_acl['playerid'];
new_acl.group = curr_acl['group'].encode( "UTF-8" );
new_acl.allow = curr_acl['allow'];
new_acl.deny = curr_acl['deny'];
newacls.append( new_acl );
for curr_group in acl.groups:
new_group = Murmur.Group()
new_group.name = curr_group['name'].encode( "UTF-8" );
new_group.inherited = curr_group['inherited'];
new_group.inherit = curr_group['inherit'];
new_group.inheritable = curr_group['inheritable'];
new_group.add = curr_group['add'];
new_group.remove = curr_group['remove'];
new_group.members = curr_group['members'];
newgroups.append( new_group );
self._getIceServerObject(srvid).setACL( acl.channelId, newacls, newgroups, acl.inherit );
ice_acls = [];
for rule in acls:
ice_rule = Murmur.ACL();
ice_rule.applyHere = rule.applyHere;
ice_rule.applySubs = rule.applySubs;
ice_rule.inherited = rule.inherited;
ice_rule.playerid = rule.userid;
ice_rule.group = rule.group;
ice_rule.allow = rule.allow;
ice_rule.deny = rule.deny;
ice_acls.append(ice_rule);
return self._getIceServerObject(srvid).setACL( channelid, ice_acls, groups, inherit );
@protectDjangoErrPage @protectDjangoErrPage
def getTexture(self, srvid, mumbleid): def getTexture(self, srvid, mumbleid):
@ -359,53 +346,9 @@ class MumbleCtlIce_120(MumbleCtlIce_118):
@protectDjangoErrPage @protectDjangoErrPage
def getACL(self, srvid, channelid): def getACL(self, srvid, channelid):
import Murmur
acls = self._getIceServerObject(srvid).getACL(channelid)
ret = []
for x in acls:
if isinstance(x, list):
tmp = []
for y in x:
if y.__class__ is Murmur.ACL:
tmp.append([y.applyHere, y.applySubs, y.inherited, y.userid, self.setUnicodeFlag(y.group), y.allow, y.deny])
elif y.__class__ is Murmur.Group:
tmp.append([self.setUnicodeFlag(y.name), y.inherited, y.inherit, y.inheritable, y.add, y.remove, y.members])
ret.append(tmp)
else:
ret.append(x)
return ret
return self._getIceServerObject(srvid).getACL(channelid)
@protectDjangoErrPage @protectDjangoErrPage
def setACL(self, srvid, acl):
import Murmur
newacls = [];
newgroups = [];
for curr_acl in acl.acls:
new_acl = Murmur.ACL();
new_acl.applyHere = curr_acl['applyHere'];
new_acl.applySubs = curr_acl['applySubs'];
new_acl.inherited = curr_acl['inherited'];
new_acl.userid = curr_acl['playerid'];
new_acl.group = curr_acl['group'].encode( "UTF-8" );
new_acl.allow = curr_acl['allow'];
new_acl.deny = curr_acl['deny'];
newacls.append( new_acl );
for curr_group in acl.groups:
new_group = Murmur.Group()
new_group.name = curr_group['name'].encode( "UTF-8" );
new_group.inherited = curr_group['inherited'];
new_group.inherit = curr_group['inherit'];
new_group.inheritable = curr_group['inheritable'];
new_group.add = curr_group['add'];
new_group.remove = curr_group['remove'];
new_group.members = curr_group['members'];
newgroups.append( new_group );
self._getIceServerObject(srvid).setACL( acl.channelId, newacls, newgroups, acl.inherit );
def setACL(self, srvid, channelid, acls, groups, inherit):
return self._getIceServerObject(srvid).setACL( channelid, acls, groups, inherit );

2
pyweb/mumble/mctl.py

@ -82,7 +82,7 @@ class MumbleCtlBase (object):
def getACL(self, srvid, channelid): def getACL(self, srvid, channelid):
raise NotImplementedError( "mctl::getACL" ); raise NotImplementedError( "mctl::getACL" );
def setACL(self, srvid, acl):
def setACL(self, srvid, channelid, acl, groups, inherit):
raise NotImplementedError( "mctl::setACL" ); raise NotImplementedError( "mctl::setACL" );
def getTexture(self, srvid, mumbleid): def getTexture(self, srvid, mumbleid):

90
pyweb/mumble/mmobjects.py

@ -44,6 +44,8 @@ class mmChannel( object ):
if self.parent is not None: if self.parent is not None:
self.parent.subchans.append( self ); self.parent.subchans.append( self );
self._acl = None;
# Lookup unknown attributes in self.channelObj to automatically include Murmur's fields # Lookup unknown attributes in self.channelObj to automatically include Murmur's fields
def __getattr__( self, key ): def __getattr__( self, key ):
if hasattr( self.channelObj, key ): if hasattr( self.channelObj, key ):
@ -58,6 +60,16 @@ class mmChannel( object ):
return self.parent.parentChannels() + [self.parent.name]; return self.parent.parentChannels() + [self.parent.name];
def getACL( self ):
""" Retrieve the ACL for this channel. """
if not self._acl:
self._acl = mmACL( self, self.server.ctl.getACL( self.server.srvid, self.chanid ) );
return self._acl;
acl = property( getACL, doc=getACL.__doc__ );
is_server = False; is_server = False;
is_channel = True; is_channel = True;
is_player = False; is_player = False;
@ -213,34 +225,56 @@ class mmPlayer( object ):
class mmACL: class mmACL:
"""Represents an ACL for a certain channel.""" """Represents an ACL for a certain channel."""
def __init__( self, channelId, aclObj ):
aclsrc, groupsrc, inherit = aclObj;
self.channelId = channelId;
self.acls = [];
for line in aclsrc:
acl = {};
acl['applyHere'], acl['applySubs'], acl['inherited'], acl['playerid'], acl['group'], acl['allow'], acl['deny'] = line;
self.acls.append( acl );
self.groups = [];
for line in groupsrc:
group = {};
group['name'], group['inherited'], group['inherit'], group['inheritable'], group['add'], group['remove'], group['members'] = line;
self.groups.append( group );
if group['name'] == "admin":
self.admingroup = group;
self.inherit = inherit;
def pack( self ):
""" Pack the information in this ACL up in a way that it can be passed to DBus. """
return (
self.channelId,
[( acl['applyHere'], acl['applySubs'], acl['inherited'], acl['playerid'], acl['group'], acl['allow'], acl['deny'] ) for acl in self.acls ],
[( group['name'], group['inherited'], group['inherit'], group['inheritable'], group['add'], group['remove'], group['members'] ) for group in self.groups ],
self.inherit
def __init__( self, channel, aclObj ):
self.channel = channel;
self.acls, self.groups, self.inherit = aclObj;
self.groups_dict = {};
for group in self.groups:
self.groups_dict[ group.name ] = group;
def groupHasMember( self, name, userid ):
""" Checks if the given userid is a member of the given group in this channel. """
if name not in self.groups_dict:
raise ReferenceError( "No such group '%s'" % name );
return userid in self.groups_dict[name].add or userid in self.groups_dict[name].members;
def groupAddMember( self, name, userid ):
""" Make sure this userid is a member of the group in this channel (and subs). """
if name not in self.groups_dict:
raise ReferenceError( "No such group '%s'" % name );
group = self.groups_dict[name];
# if neither inherited nor to be added, add
if userid not in group.members and userid not in group.add:
group.add.append( userid );
# if to be removed, unremove
if userid in group.remove:
group.remove.remove( userid );
def groupRemoveMember( self, name, userid ):
""" Make sure this userid is NOT a member of the group in this channel (and subs). """
if name not in self.groups_dict:
raise ReferenceError( "No such group '%s'" % name );
group = self.groups_dict[name];
# if added here, unadd
if userid in group.add:
group.add.remove( userid );
# if member and not in remove, add to remove
elif userid in group.members and userid not in group.remove:
group.remove.append( userid );
def save( self ):
return self.channel.server.ctl.setACL(
self.channel.server.srvid,
self.channel.chanid,
self.acls, self.groups, self.inherit
); );

29
pyweb/mumble/models.py

@ -446,39 +446,28 @@ class MumbleUser( models.Model ):
# Don't save the users' passwords, we don't need them anyway # Don't save the users' passwords, we don't need them anyway
self.password = ''; self.password = '';
self.setAdmin( self.isAdmin );
self.aclAdmin = self.isAdmin;
# Now allow django to save the record set # Now allow django to save the record set
return models.Model.save( self ); return models.Model.save( self );
# Admin handlers # Admin handlers
def getAdmin( self ): def getAdmin( self ):
"""Get ACL of root Channel, get the admin group and see if this user is in it.""" """Get ACL of root Channel, get the admin group and see if this user is in it."""
acl = mmACL( 0, self.server.ctl.getACL(self.server.srvid, 0) );
if not hasattr( acl, "admingroup" ):
raise ReferenceError( _( "The admin group was not found in the ACL's groups list!" ) );
return self.mumbleid in acl.admingroup['add'];
return self.server.rootchan.acl.groupHasMember( "admin", self.mumbleid );
def setAdmin( self, value ): def setAdmin( self, value ):
"""Set or revoke this user's membership in the admin group on the root channel.""" """Set or revoke this user's membership in the admin group on the root channel."""
ctl = self.server.ctl;
acl = mmACL( 0, ctl.getACL(self.server.srvid, 0) );
if not hasattr( acl, "admingroup" ):
raise ReferenceError( _( "The admin group was not found in the ACL's groups list!" ) );
if value != ( self.mumbleid in acl.admingroup['add'] ):
if value:
acl.admingroup['add'].append( self.mumbleid );
else:
acl.admingroup['add'].remove( self.mumbleid );
ctl.setACL(self.server.srvid, acl);
if value:
self.server.rootchan.acl.groupAddMember( "admin", self.mumbleid );
else:
self.server.rootchan.acl.groupRemoveMember( "admin", self.mumbleid );
self.server.rootchan.acl.save();
return value; return value;
aclAdmin = property( getAdmin, setAdmin, doc="Wrapper around getAdmin/setAdmin (not a database field like isAdmin)" );
# Registration fetching # Registration fetching
def getRegistration( self ): def getRegistration( self ):
"""Retrieve a user's registration from Murmur as a dict.""" """Retrieve a user's registration from Murmur as a dict."""

Loading…
Cancel
Save