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.

236 lines
9.0 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
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. from pyweb.settings import DEFAULT_FROM_EMAIL
  31. import dbus
  32. import socket
  33. class Mumble( models.Model ):
  34. name = models.CharField( 'Server Name', max_length = 200 );
  35. dbus = models.CharField( 'DBus base', max_length = 200, default = 'net.sourceforge.mumble.murmur' );
  36. srvid = models.IntegerField( 'Server ID', editable = False );
  37. addr = models.CharField( 'Server Address', max_length = 200 );
  38. port = models.IntegerField( 'Server Port', blank = True, null = True );
  39. url = models.CharField( 'Website URL', max_length = 200, blank = True );
  40. motd = models.TextField( 'Welcome Message', blank = True );
  41. passwd = models.CharField( 'Server Password', max_length = 200, blank = True );
  42. supw = models.CharField( 'Superuser Password', max_length = 200, blank = True );
  43. users = models.IntegerField( 'Max. Users', blank = True, null = True );
  44. bwidth = models.IntegerField( 'Bandwidth [Bps]', blank = True, null = True );
  45. sslcrt = models.TextField( 'SSL Certificate', blank = True );
  46. sslkey = models.TextField( 'SSL Key', blank = True );
  47. booted = models.BooleanField( 'Boot Server', default = True );
  48. def getDbusMeta( self ):
  49. return dbus.Interface( dbus.SystemBus().get_object( self.dbus, '/' ), 'net.sourceforge.mumble.Meta' );
  50. def getDbusObject( self ):
  51. "Connects to DBus and returns an mmServer object representing this Murmur instance."
  52. bus = dbus.SystemBus();
  53. murmur = dbus.Interface( bus.get_object( self.dbus, '/' ), 'net.sourceforge.mumble.Meta');
  54. if self.srvid not in murmur.getBootedServers():
  55. raise Exception, 'No murmur process with the given server ID (%d) is running and attached to system dbus under %s.' % ( self.srvid, self.dbus );
  56. return dbus.Interface( bus.get_object( self.dbus, '/%d' % self.srvid ), 'net.sourceforge.mumble.Murmur' );
  57. def getServerObject( self ):
  58. return mmServer( self.srvid, self.getDbusObject(), self.name );
  59. def __unicode__( self ):
  60. return u'Murmur "%s" (%d)' % ( self.name, self.srvid );
  61. def save( self, dontConfigureMurmur=False ):
  62. if dontConfigureMurmur:
  63. # skip murmur configuration, e.g. because we're inserting models for existing servers.
  64. return models.Model.save( self );
  65. # Prior to saving the model, connect to murmur via dbus and update its settings.
  66. murmur = self.getDbusMeta();
  67. # check if this server already exists, if not call newServer and set my srvid first
  68. if self.id is None:
  69. self.srvid = murmur.newServer();
  70. srvid = dbus.Int32( self.srvid );
  71. murmur.setConf( srvid, 'host', socket.gethostbyname( self.addr ) );
  72. murmur.setConf( srvid, 'registerName', self.name );
  73. murmur.setConf( srvid, 'registerUrl', self.url );
  74. murmur.setConf( srvid, 'welcometext', self.motd );
  75. murmur.setConf( srvid, 'password', self.passwd );
  76. murmur.setConf( srvid, 'certificate', self.sslcrt );
  77. murmur.setConf( srvid, 'key', self.sslkey );
  78. if self.port is not None:
  79. murmur.setConf( srvid, 'port', str(self.port) );
  80. else:
  81. murmur.setConf( srvid, 'port', '' );
  82. if self.users is not None:
  83. murmur.setConf( srvid, 'users', str(self.users) );
  84. else:
  85. murmur.setConf( srvid, 'users', '' );
  86. if self.bwidth is not None:
  87. murmur.setConf( srvid, 'bandwidth', str(self.bwidth) );
  88. else:
  89. murmur.setConf( srvid, 'bandwidth', '' );
  90. # registerHostname needs to take the port no into account
  91. if self.port and self.port != 64738:
  92. murmur.setConf( srvid, 'registerHostname', "%s:%d" % ( self.addr, self.port ) );
  93. else:
  94. murmur.setConf( srvid, 'registerHostname', self.addr );
  95. if self.supw:
  96. murmur.setSuperUserPassword( srvid, self.supw );
  97. self.supw = '';
  98. if self.booted != murmur.isBooted( srvid ):
  99. if self.booted:
  100. murmur.start( srvid );
  101. else:
  102. murmur.stop( srvid );
  103. # Now allow django to save the record set
  104. return models.Model.save( self );
  105. def deleteServer( self ):
  106. srvid = dbus.Int32( self.srvid );
  107. murmur = self.getDbusMeta();
  108. if murmur.isBooted( srvid ):
  109. murmur.stop( srvid );
  110. murmur.deleteServer( srvid );
  111. @staticmethod
  112. def pre_delete_listener( **kwargs ):
  113. kwargs['instance'].deleteServer();
  114. class MumbleUser( models.Model ):
  115. mumbleid = models.IntegerField( 'Mumble player_id', editable = False, default = -1 );
  116. name = models.CharField( 'User name and Login', max_length = 200 );
  117. password = models.CharField( 'Login password', max_length = 200, blank=True );
  118. server = models.ForeignKey( Mumble );
  119. owner = models.ForeignKey( User, null=True, blank=True );
  120. isAdmin = models.BooleanField( 'Admin on root channel', default = False );
  121. def __unicode__( self ):
  122. return u"Mumble user %s on %s owned by Django user %s" % ( self.name, self.server, self.owner );
  123. def save( self, dontConfigureMurmur=False ):
  124. if dontConfigureMurmur:
  125. # skip murmur configuration, e.g. because we're inserting models for existing players.
  126. return models.Model.save( self );
  127. # Before the record set is saved, update Murmur via dbus.
  128. murmur = self.server.getDbusObject();
  129. if self.id is None:
  130. # This is a new user record, so Murmur doesn't know about it yet
  131. self.mumbleid = murmur.registerPlayer( dbus.String( self.name ) );
  132. # Update user's registration
  133. if self.password:
  134. murmur.setRegistration(
  135. dbus.Int32( self.mumbleid ),
  136. dbus.String( self.name ),
  137. dbus.String( self.owner.email if self.owner else DEFAULT_FROM_EMAIL ),
  138. dbus.String( self.password )
  139. );
  140. # Don't save the users' passwords, we don't need them anyway
  141. self.password = '';
  142. self.setAdmin( self.isAdmin );
  143. # Now allow django to save the record set
  144. return models.Model.save( self );
  145. def getAdmin( self ):
  146. # Get ACL of root Channel, get the admin group and see if I'm in it
  147. bus = self.server.getDbusObject();
  148. acl = mmACL( 0, bus.getACL(0) );
  149. if not hasattr( acl, "admingroup" ):
  150. raise ValueError( "The admin group was not found in the ACL's groups list!" );
  151. return self.mumbleid in acl.admingroup['add'];
  152. def setAdmin( self, value ):
  153. # Get ACL of root Channel, get the admin group and see if I'm in it
  154. bus = self.server.getDbusObject();
  155. acl = mmACL( 0, bus.getACL(0) );
  156. if not hasattr( acl, "admingroup" ):
  157. raise ValueError( "The admin group was not found in the ACL's groups list!" );
  158. if value != ( self.mumbleid in acl.admingroup['add'] ):
  159. if value:
  160. acl.admingroup['add'].append( dbus.Int32(self.mumbleid) );
  161. else:
  162. acl.admingroup['add'].remove( self.mumbleid );
  163. bus.setACL( *acl.pack() );
  164. return value;
  165. @staticmethod
  166. def pre_delete_listener( **kwargs ):
  167. kwargs['instance'].unregister();
  168. def unregister( self ):
  169. # Unregister this player in Murmur via dbus.
  170. murmur = self.server.getDbusObject();
  171. murmur.unregisterPlayer( dbus.Int32( self.mumbleid ) );
  172. from django.db.models import signals
  173. signals.pre_delete.connect( Mumble.pre_delete_listener, sender=Mumble );
  174. signals.pre_delete.connect( MumbleUser.pre_delete_listener, sender=MumbleUser );