Forked mumble-django project from https://bitbucket.org/Svedrin/mumble-django
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
8.9 KiB

16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
  1. """ This file is part of the mumble-django application.
  2. Copyright (C) 2009, Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. - Redistributions of source code must retain the above copyright notice,
  8. this list of conditions and the following disclaimer.
  9. - Redistributions in binary form must reproduce the above copyright notice,
  10. this list of conditions and the following disclaimer in the documentation
  11. and/or other materials provided with the distribution.
  12. - Neither the name of the Mumble Developers nor the names of its
  13. contributors may be used to endorse or promote products derived from this
  14. software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  16. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  17. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  18. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
  19. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  21. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  22. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  23. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  24. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. """
  27. from django.contrib.auth.models import User
  28. from django.db import models
  29. from mmobjects import mmServer, mmACL
  30. import dbus
  31. import socket
  32. class Mumble( models.Model ):
  33. name = models.CharField( 'Server Name', max_length = 200 );
  34. dbus = models.CharField( 'DBus base', max_length = 200, default = 'net.sourceforge.mumble.murmur' );
  35. srvid = models.IntegerField( 'Server ID', editable = False );
  36. addr = models.CharField( 'Server Address', max_length = 200 );
  37. port = models.IntegerField( 'Server Port', blank = True, null = True );
  38. url = models.CharField( 'Website URL', max_length = 200, blank = True );
  39. motd = models.TextField( 'Welcome Message', blank = True );
  40. passwd = models.CharField( 'Server Password', max_length = 200, blank = True );
  41. supw = models.CharField( 'Superuser Password', max_length = 200, blank = True );
  42. users = models.IntegerField( 'Max. Users', blank = True, null = True );
  43. bwidth = models.IntegerField( 'Bandwidth [Bps]', blank = True, null = True );
  44. sslcrt = models.TextField( 'SSL Certificate', blank = True );
  45. sslkey = models.TextField( 'SSL Key', blank = True );
  46. booted = models.BooleanField( 'Boot Server', default = True );
  47. def getDbusMeta( self ):
  48. return dbus.Interface( dbus.SystemBus().get_object( self.dbus, '/' ), 'net.sourceforge.mumble.Meta' );
  49. def getDbusObject( self ):
  50. "Connects to DBus and returns an mmServer object representing this Murmur instance."
  51. bus = dbus.SystemBus();
  52. murmur = dbus.Interface( bus.get_object( self.dbus, '/' ), 'net.sourceforge.mumble.Meta');
  53. if self.srvid not in murmur.getBootedServers():
  54. raise Exception, 'No murmur process with the given server ID (%d) is running and attached to system dbus under %s.' % ( self.srvid, self.dbus );
  55. return dbus.Interface( bus.get_object( self.dbus, '/%d' % self.srvid ), 'net.sourceforge.mumble.Murmur' );
  56. def getServerObject( self ):
  57. return mmServer( self.srvid, self.getDbusObject(), self.name );
  58. def __unicode__( self ):
  59. return u'Murmur "%s" (%d)' % ( self.name, self.srvid );
  60. def save( self, dontConfigureMurmur=False ):
  61. if dontConfigureMurmur:
  62. # skip murmur configuration, e.g. because we're inserting models for existing servers.
  63. return models.Model.save( self );
  64. # Prior to saving the model, connect to murmur via dbus and update its settings.
  65. murmur = self.getDbusMeta();
  66. # check if this server already exists, if not call newServer and set my srvid first
  67. if self.id is None:
  68. self.srvid = murmur.newServer();
  69. srvid = dbus.Int32( self.srvid );
  70. murmur.setConf( srvid, 'host', socket.gethostbyname( self.addr ) );
  71. murmur.setConf( srvid, 'registerName', self.name );
  72. murmur.setConf( srvid, 'registerUrl', self.url );
  73. murmur.setConf( srvid, 'welcometext', self.motd );
  74. murmur.setConf( srvid, 'password', self.passwd );
  75. murmur.setConf( srvid, 'certificate', self.sslcrt );
  76. murmur.setConf( srvid, 'key', self.sslkey );
  77. if self.port is not None:
  78. murmur.setConf( srvid, 'port', str(self.port) );
  79. else:
  80. murmur.setConf( srvid, 'port', '' );
  81. if self.users is not None:
  82. murmur.setConf( srvid, 'users', str(self.users) );
  83. else:
  84. murmur.setConf( srvid, 'users', '' );
  85. if self.bwidth is not None:
  86. murmur.setConf( srvid, 'bandwidth', str(self.bwidth) );
  87. else:
  88. murmur.setConf( srvid, 'bandwidth', '' );
  89. # registerHostname needs to take the port no into account
  90. if self.port and self.port != 64738:
  91. murmur.setConf( srvid, 'registerHostname', "%s:%d" % ( self.addr, self.port ) );
  92. else:
  93. murmur.setConf( srvid, 'registerHostname', self.addr );
  94. if self.supw:
  95. murmur.setSuperUserPassword( srvid, self.supw );
  96. self.supw = '';
  97. if self.booted != murmur.isBooted( srvid ):
  98. if self.booted:
  99. murmur.start( srvid );
  100. else:
  101. murmur.stop( srvid );
  102. # Now allow django to save the record set
  103. return models.Model.save( self );
  104. def deleteServer( self ):
  105. srvid = dbus.Int32( self.srvid );
  106. murmur = self.getDbusMeta();
  107. if murmur.isBooted( srvid ):
  108. murmur.stop( srvid );
  109. murmur.deleteServer( srvid );
  110. @staticmethod
  111. def pre_delete_listener( **kwargs ):
  112. kwargs['instance'].deleteServer();
  113. class MumbleUser( models.Model ):
  114. mumbleid = models.IntegerField( 'Mumble player_id', editable = False, default = -1 );
  115. name = models.CharField( 'User name and Login', max_length = 200 );
  116. password = models.CharField( 'Login password', max_length = 200, blank=True );
  117. server = models.ForeignKey( Mumble );
  118. owner = models.ForeignKey( User, null=True, blank=True );
  119. isAdmin = models.BooleanField( 'Admin on root channel', default = False );
  120. def __unicode__( self ):
  121. return u"Mumble user %s on %s owned by Django user %s" % ( self.name, self.server, self.owner );
  122. def save( self, dontConfigureMurmur=False ):
  123. if dontConfigureMurmur:
  124. # skip murmur configuration, e.g. because we're inserting models for existing players.
  125. return models.Model.save( self );
  126. # Before the record set is saved, update Murmur via dbus.
  127. murmur = self.server.getDbusObject();
  128. if self.id is None:
  129. # This is a new user record, so Murmur doesn't know about it yet
  130. self.mumbleid = murmur.registerPlayer( dbus.String( self.name ) );
  131. # Update user's registration
  132. if self.password and self.owner:
  133. murmur.setRegistration(
  134. dbus.Int32( self.mumbleid ),
  135. dbus.String( self.name ),
  136. dbus.String( self.owner.email ),
  137. dbus.String( self.password )
  138. );
  139. # Don't save the users' passwords, we don't need them anyway
  140. self.password = '';
  141. self.setAdmin( self.isAdmin );
  142. # Now allow django to save the record set
  143. return models.Model.save( self );
  144. def getAdmin( self ):
  145. # Get ACL of root Channel, get the admin group and see if I'm in it
  146. bus = self.server.getDbusObject();
  147. acl = mmACL( 0, bus.getACL(0) );
  148. if not hasattr( acl, "admingroup" ):
  149. raise ValueError( "The admin group was not found in the ACL's groups list!" );
  150. return self.mumbleid in acl.admingroup['add'];
  151. def setAdmin( self, value ):
  152. # Get ACL of root Channel, get the admin group and see if I'm in it
  153. bus = self.server.getDbusObject();
  154. acl = mmACL( 0, bus.getACL(0) );
  155. if not hasattr( acl, "admingroup" ):
  156. raise ValueError( "The admin group was not found in the ACL's groups list!" );
  157. if value != ( self.mumbleid in acl.admingroup['add'] ):
  158. if value:
  159. acl.admingroup['add'].append( dbus.Int32(self.mumbleid) );
  160. else:
  161. acl.admingroup['add'].remove( self.mumbleid );
  162. bus.setACL( *acl.pack() );
  163. return value;
  164. @staticmethod
  165. def pre_delete_listener( **kwargs ):
  166. kwargs['instance'].unregister();
  167. def unregister( self ):
  168. # Unregister this player in Murmur via dbus.
  169. murmur = self.server.getDbusObject();
  170. murmur.unregisterPlayer( dbus.Int32( self.mumbleid ) );
  171. from django.db.models import signals
  172. signals.pre_delete.connect( Mumble.pre_delete_listener, sender=Mumble );
  173. signals.pre_delete.connect( MumbleUser.pre_delete_listener, sender=MumbleUser );