Reorganise the file structure into a project tree

This commit is contained in:
2011-03-11 12:58:50 +00:00
parent 58b1691638
commit 3686aa7523
226 changed files with 7 additions and 5 deletions

View File

@@ -0,0 +1,84 @@
import settings
from django.db import connections
def get_api(api):
if settings.DISABLE_SERVICES:
return BaseService()
try:
mod = __import__(api)
except ImportError:
raise Exception('Error creating service')
for i in api.split(".")[1:]:
mod = getattr(mod, i)
return getattr(mod, mod.ServiceClass)()
def list_apis():
import os.path, pkgutil
pkgpath = os.path.dirname(__file__)
return [name for _, name, _ in pkgutil.iter_modules([pkgpath])]
class BaseService():
"""
Base Service class, all service classes should inherit from this
"""
settings = { 'require_user': True,
'require_password': True,
'provide_login': False }
def add_user(self, username, password, **kwargs):
""" Add a user, returns a dict for that user """
return { 'username': username, 'password': password }
def check_user(self, username):
""" Check if the username exists """
return False
def check_uid(self, uid):
""" Check if a UID exists """
return self.check_user(uid)
def delete_user(self, uid):
""" Delete a user by uid """
return True
def disable_user(self, uid):
""" Disable a user by uid """
return True
def enable_user(self, uid, password):
""" Enable a user by uid """
return True
def reset_password(self, uid, password):
""" Reset the user's password """
return True
def login(self, uid):
""" Login the user and provide cookies back """
pass
def update_groups(self, uid, groups, character=None):
"""" Update the UID's groups based on the provided list """
pass
class BaseDBService(BaseService):
@property
def db(self):
if not hasattr(self, '_db'):
self._db = connections[self.settings['database_name']]
return self._db
@property
def dbcursor(self):
if not hasattr(self, '_dbcursor'):
self._dbcursor = self.db.cursor()
return self._dbcursor

View File

@@ -0,0 +1,8 @@
from sso.services import BaseService
class DummyService(BaseService):
""" Always passes, good for a test service """
pass
ServiceClass = 'DummyService'

View File

@@ -0,0 +1,87 @@
import xmlrpclib
from sso.services import BaseService
import settings
from hashlib import md5
class IPBService(BaseService):
settings = { 'require_user': True,
'require_password': True,
'provide_login': False,
'use_auth_username': True,
'ipb_display_name': "[%(corp)s] - %(name)s",
'ipb_endpoint': 'http://testboard.aevumdecessus.com/interface/board/index.php',
'ipb_api_key': '51242ecca069b986106f04db1047cfc4',
'ipb_api_module': 'ipb' }
def exec_xmlrpc(self, func, **kwargs):
""" Send a XMLRPC request """
if not hasattr(self, '_server'):
self._server = xmlrpclib.Server(self.settings['ipb_endpoint'], verbose=True)
params = {}
for i in kwargs:
params[i] = kwargs[i]
params['api_key'] = self.settings['ipb_api_key']
params['api_module'] = self.settings['ipb_api_module']
return getattr(self._server, func)(params)
def _create_group(self, name):
""" Creates a IPB membergroup """
ret = self.exec_xmlrpc('createGroup', group_name=name)
if ret:
return {'name': name, 'id': ret['changeSuccessful']}
def add_user(self, username, password, **kwargs):
""" Add user to service """
password = md5(password).hexdigest()
details = { 'name': kwargs['character'].name,
'alli': kwargs['character'].corporation.alliance.ticker,
'corp': kwargs['character'].corporation.ticker }
display = self.settings['ipb_display_name'] % details
ret = self.exec_xmlrpc('createUser', username=username, email=kwargs['user'].email, display_name=display, password=password)
return username
def delete_user(self, uid):
""" Delete a user """
pass
def check_user(self, username):
""" Check if the username exists """
ret = self.exec_xmlrpc('fetchMember', search_type='email', search_string=username)
return ret
def disable_user(self, uid):
""" Disable a user """
pass
def enable_user(self, uid, password):
""" Enable a user """
pass
def reset_password(self, uid, password):
""" Reset the user's password """
pass
def update_groups(self, uid, groups, character=None):
user_id = self.check_user(uid)
# Get all IPB groups
# Iterate through the provided group list and create any missing ones
grplist = []
for g in groups:
if not g.name in grplist:
ret = self._create_group(g.name)
if ret:
grplist[ret['name']] = ret['id']
# Assign each group to the user id
for gk in grplist:
self.exec_xmlrpc('updateUserGroup', user_id=user_id, group_name=gk, action='ADD')
ServiceClass = 'IPBService'

View File

@@ -0,0 +1,151 @@
import xmlrpclib
from sso.services import BaseService
import settings
class JabberService(BaseService):
settings = { 'require_user': True,
'require_password': True,
'provide_login': False,
'use_auth_username': False,
'jabber_server': 'dredd.it',
'jabber_xmlrpc_url': 'http://127.0.0.1:4560',
'jabber_annouce_from': 'announcebot@pleaseignore.com'}
def exec_xmlrpc(self, func, **kwargs):
""" Send a XMLRPC request """
if not hasattr(self, '_server'):
self._server = xmlrpclib.Server(self.settings['jabber_xmlrpc_url'])
params = {}
for i in kwargs:
params[i] = kwargs[i]
return getattr(self._server, func)(params)
def add_user(self, username, password, **kwargs):
""" Add user to service """
username = username.lower()
res = self.exec_xmlrpc('register', user=username, host=self.settings['jabber_server'], password=password)
if res['res'] == 0:
if 'character' in kwargs:
self.exec_xmlrpc('set_nickname', user=username, host=self.settings['jabber_server'], nickname=kwargs['character'].name)
self.exec_xmlrpc('set_vcard2', user=username, host=self.settings['jabber_server'], name='ORG', subname='ORGNAME', content=kwargs['character'].corporation.name)
uid = "%s@%s" % (username.lower(), self.settings['jabber_server'])
if 'user' in kwargs:
self.update_groups(uid, kwargs['user'].groups.all())
return { 'username': uid, 'password': password }
else:
return False
def delete_user(self, uid):
""" Delete a user """
username, server = uid.lower().split("@")
for group in self.get_user_groups(uid):
self.exec_xmlrpc('srg_user_del', user=username, host=server, group=group, grouphost=server)
res = self.exec_xmlrpc('unregister', user=username, host=server)
if res['res'] == 0:
return True
else:
return False
def check_user(self, username):
""" Check if the username exists """
if '@' in username:
username, server = username.lower().split("@")
else:
server = self.settings['jabber_server']
res = self.exec_xmlrpc('check_account', user=username, host=server)
if res['res'] == 0:
return True
else:
return False
def disable_user(self, uid):
""" Disable a user """
username, server = uid.lower().split("@")
res = self.exec_xmlrpc('ban_account', host=server, user=username, reason='Auth account disable')
if res['res'] == 0:
return True
else:
return False
def enable_user(self, uid, password):
""" Enable a user """
self.reset_password(uid, password)
def reset_password(self, uid, password):
""" Reset the user's password """
username, server = uid.lower().split("@")
res = self.exec_xmlrpc('change_password', user=username, host=server, newpass=password)
if res['res'] == 0:
return True
else:
return False
def get_group_list(self, server):
srvgrp = self.exec_xmlrpc('srg_list', host=server)
return [grp['id'].lower() for grp in srvgrp['groups']]
def get_group_members(self, server, group):
members = self.exec_xmlrpc('srg_get_members', group=group, host=server)
return [x['member'].lower() for x in members['members']]
def get_user_groups(self, uid):
grouplist = []
username, server = uid.lower().split("@")
for grp in self.get_group_list(server):
if uid in self.get_group_members(server, grp):
grouplist.append(grp)
return grouplist
def update_groups(self, uid, groups, character=None):
username, server = uid.lower().split("@")
current_groups = self.get_user_groups(uid)
valid_groups = []
for group in groups:
groupname = group.name.lower().replace(' ', '-')
self.exec_xmlrpc('srg_create', group=groupname, host=server, name=group.name, description='', display='')
self.exec_xmlrpc('srg_user_add', user=username, host=server, group=groupname, grouphost=server)
valid_groups.append(groupname)
for group in (set(current_groups) - set(valid_groups)):
self.exec_xmlrpc('srg_user_del', user=username, host=server, group=groupname, grouphost=server)
def send_message(self, jid, msg):
# send_stanza_c2s user host resource stanza
username, server = jid.lower().split("@")
self.exec_xmlrpc('send_stanza_c2s', user=username, host=server, resource='auth', stanza=str(msg))
def announce(self, server, message, subject=None, all=False, users=[], groups=[]):
import xmpp
msg = xmpp.protocol.Message()
msg.setFrom(self.settings['jabber_announce_from'])
msg.setBody(message)
if subject:
msg.setSubject(subject)
if all:
msg.setTo('%s/announce/all-hosts/online' % server)
self.send_message(self.settings['jabber_announce_from'], msg)
return True
else:
if len(users):
for u in set(users):
msg.setTo(u)
self.send_message(self.settings['jabber_announce_from'], msg)
return True
elif len(groups):
tolist = []
for g in groups:
tolist.extend([x for x in self.get_group_members(server, g)])
return self.announce(server, message, subject, users=tolist)
else:
return False
ServiceClass = 'JabberService'

View File

@@ -0,0 +1,86 @@
import crypt
import random
import time
from django.db import transaction
from sso.services import BaseDBService
import settings
class MiningBuddyService(BaseDBService):
"""
Mining Buddy Class, allows registration and sign-in
"""
settings = { 'require_user': False,
'require_password': False,
'provide_login': False,
'use_auth_username': False,
'database_name': 'dreddit_mining',
'password_salt': 's98ss7fsc7fd2rf62ctcrlwztstnzve9toezexcsdhfgviuinusxcdtsvbrg' }
SQL_ADD_USER = r"INSERT INTO users (username, password, email, emailvalid, confirmed, rank) VALUES (%s, %s, %s, 1, 1, 2)"
SQL_ADD_API = r"INSERT INTO api_keys (userid, time, apiID, apiKey, api_valid, charid) values (%s, %s, %s, %s, 1, %s)"
SQL_DIS_USER = r"UPDATE users SET canLogin = 0 WHERE username = %s"
SQL_ENABLE_USER = r"UPDATE users SET canLogin = 1, password = %s WHERE username = %s"
SQL_CHECK_USER = r"SELECT username from users WHERE username = %s and deleted = 0"
SQL_DEL_USER = r"UPDATE users set deleted = 1 WHERE username = %s"
def _gen_salt(self):
return self.settings['password_salt']
def _gen_mb_hash(self, password, salt=None):
if not salt:
salt = self._gen_salt()
return crypt.crypt(password, salt)
def _clean_username(self, username):
username = username.strip()
return username
def add_user(self, username, password, **kwargs):
""" Add a user """
pwhash = self._gen_mb_hash(password)
if 'user' in kwargs:
email = kwargs['user'].email
else:
email = ''
self.dbcursor.execute(self.SQL_ADD_USER, [self._clean_username(username), pwhash, email])
userid = self.dbcursor.lastrowid
api = kwargs['character'].eveaccount_set.all()[0]
self.dbcursor.execute(self.SQL_ADD_API, [userid, int(time.time()), api.api_user_id, api.api_key, kwargs['character'].id])
return { 'username': self._clean_username(username), 'password': password }
def check_user(self, username):
""" Check if the username exists """
self.dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
row = self.dbcursor.fetchone()
if row:
return True
return False
def delete_user(self, uid):
""" Delete a user """
self.dbcursor.execute(self.SQL_DEL_USER, [uid])
return True
def disable_user(self, uid):
""" Disable a user """
self.dbcursor.execute(self.SQL_DIS_USER, [uid])
return True
def enable_user(self, uid, password):
""" Enable a user """
pwhash = self._gen_mb_hash(password)
self.dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, uid])
return True
def reset_password(self, uid, password):
""" Reset the user's password """
return self.enable_user(uid, password)
ServiceClass = 'MiningBuddyService'

View File

@@ -0,0 +1,610 @@
# -*- coding: utf-8 -*-
"""
* Copyright © 2009, withgod <withgod@sourceforge.net>
* 2009-2010, Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
*
* Mumble-Django is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
"""
from time import time
from functools import wraps
from StringIO import StringIO
from os.path import exists, join
from os import unlink, name as os_name
from PIL import Image
from struct import pack, unpack
from zlib import compress, decompress, error
from mctl import MumbleCtlBase
import Ice, IcePy, tempfile
class ObjectInfo( object ):
""" Wraps arbitrary information to be easily accessed. """
def __init__( self, **kwargs ):
self.__dict__ = kwargs;
def __str__( self ):
return unicode( self );
def __repr__( self ):
return unicode( self );
def __unicode__( self ):
return unicode( self.__dict__ );
def __getitem__(self, key):
return self.__dict__[key]
def protectDjangoErrPage( func ):
""" Catch and reraise Ice exceptions to prevent the Django page from failing.
Since I need to "import Murmur", Django would try to read a murmur.py file
which doesn't exist, and thereby produce an IndexError exception. This method
erases the exception's traceback, preventing Django from trying to read any
non-existant files and borking.
"""
@wraps(func)
def protection_wrapper( self, *args, **kwargs ):
""" Call the original function and catch Ice exceptions. """
try:
return func( self, *args, **kwargs );
except Ice.Exception, err:
raise err;
protection_wrapper.innerfunc = func
return protection_wrapper;
@protectDjangoErrPage
def MumbleCtlIce( connstring, slicefile=None, icesecret=None ):
""" Choose the correct Ice handler to use (1.1.8 or 1.2.x), and make sure the
Murmur version matches the slice Version.
Optional parameters are the path to the slice file and the Ice secret
necessary to authenticate to Murmur.
The path can be omitted only if running Murmur 1.2.3 or later, which
exports a getSlice method to retrieve the Slice from.
"""
prop = Ice.createProperties([])
prop.setProperty("Ice.ImplicitContext", "Shared")
idd = Ice.InitializationData()
idd.properties = prop
ice = Ice.initialize(idd)
if icesecret:
ice.getImplicitContext().put( "secret", icesecret.encode("utf-8") )
prx = ice.stringToProxy( connstring.encode("utf-8") )
try:
prx.ice_ping()
except Ice.Exception:
raise EnvironmentError( "Murmur does not appear to be listening on this address (Ice ping failed)." )
try:
import Murmur
except ImportError:
# Try loading the Slice from Murmur directly via its getSlice method.
# See scripts/testdynamic.py in Mumble's Git repository.
try:
slice = IcePy.Operation( 'getSlice',
Ice.OperationMode.Idempotent, Ice.OperationMode.Idempotent,
True, (), (), (), IcePy._t_string, ()
).invoke(prx, ((), None))
except (TypeError, Ice.OperationNotExistException):
if not slicefile:
raise EnvironmentError(
"You didn't configure a slice file. Please set the SLICE variable in settings.py." )
if not exists( slicefile ):
raise EnvironmentError(
"The slice file does not exist: '%s' - please check the settings." % slicefile )
if " " in slicefile:
raise EnvironmentError(
"You have a space char in your Slice path. This will confuse Ice, please check." )
if not slicefile.endswith( ".ice" ):
raise EnvironmentError( "The slice file name MUST end with '.ice'." )
try:
Ice.loadSlice( slicefile )
except RuntimeError:
raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
else:
if os_name == "nt":
# It weren't Windows if it didn't need to be treated differently. *sigh*
temppath = join( tempfile.gettempdir(), "Murmur.ice" )
slicetemp = open( temppath, "w+b" )
try:
slicetemp.write( slice )
finally:
slicetemp.close()
try:
Ice.loadSlice( temppath )
except RuntimeError:
raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
finally:
unlink(temppath)
else:
slicetemp = tempfile.NamedTemporaryFile( suffix='.ice' )
try:
slicetemp.write( slice )
slicetemp.flush()
Ice.loadSlice( slicetemp.name )
except RuntimeError:
raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
finally:
slicetemp.close()
import Murmur
meta = Murmur.MetaPrx.checkedCast(prx)
murmurversion = meta.getVersion()[:3]
if murmurversion == (1, 1, 8):
return MumbleCtlIce_118( connstring, meta );
elif murmurversion[:2] == (1, 2):
if murmurversion[2] < 2:
return MumbleCtlIce_120( connstring, meta );
elif murmurversion[2] == 2:
return MumbleCtlIce_122( connstring, meta );
elif murmurversion[2] == 3:
return MumbleCtlIce_123( connstring, meta );
raise NotImplementedError( "No ctl object available for Murmur version %d.%d.%d" % tuple(murmurversion) )
class MumbleCtlIce_118(MumbleCtlBase):
method = "ICE";
def __init__( self, connstring, meta ):
self.proxy = connstring;
self.meta = meta;
@protectDjangoErrPage
def _getIceServerObject(self, srvid):
return self.meta.getServer(srvid);
@protectDjangoErrPage
def getBootedServers(self):
ret = []
for x in self.meta.getBootedServers():
ret.append(x.id())
return ret
@protectDjangoErrPage
def getVersion( self ):
return self.meta.getVersion();
@protectDjangoErrPage
def getAllServers(self):
ret = []
for x in self.meta.getAllServers():
ret.append(x.id())
return ret
@protectDjangoErrPage
def getRegisteredPlayers(self, srvid, filter = ''):
users = self._getIceServerObject(srvid).getRegisteredPlayers( filter.encode( "UTF-8" ) )
ret = {};
for user in users:
ret[user.playerid] = ObjectInfo(
userid = int( user.playerid ),
name = unicode( user.name, "utf8" ),
email = unicode( user.email, "utf8" ),
pw = unicode( user.pw, "utf8" )
);
return ret
@protectDjangoErrPage
def getChannels(self, srvid):
return self._getIceServerObject(srvid).getChannels();
@protectDjangoErrPage
def getPlayers(self, srvid):
users = self._getIceServerObject(srvid).getPlayers()
ret = {};
for useridx in users:
user = users[useridx];
ret[ user.session ] = ObjectInfo(
session = user.session,
userid = user.playerid,
mute = user.mute,
deaf = user.deaf,
suppress = user.suppressed,
selfMute = user.selfMute,
selfDeaf = user.selfDeaf,
channel = user.channel,
name = user.name,
onlinesecs = user.onlinesecs,
bytespersec = user.bytespersec
);
return ret;
@protectDjangoErrPage
def getDefaultConf(self):
return self.setUnicodeFlag(self.meta.getDefaultConf())
@protectDjangoErrPage
def getAllConf(self, srvid):
conf = self.setUnicodeFlag(self._getIceServerObject(srvid).getAllConf())
info = {};
for key in conf:
if key == "playername":
info['username'] = conf[key];
else:
info[str(key)] = conf[key];
return info;
@protectDjangoErrPage
def newServer(self):
return self.meta.newServer().id()
@protectDjangoErrPage
def isBooted( self, srvid ):
return bool( self._getIceServerObject(srvid).isRunning() );
@protectDjangoErrPage
def start( self, srvid ):
self._getIceServerObject(srvid).start();
@protectDjangoErrPage
def stop( self, srvid ):
self._getIceServerObject(srvid).stop();
@protectDjangoErrPage
def deleteServer( self, srvid ):
if self._getIceServerObject(srvid).isRunning():
self._getIceServerObject(srvid).stop()
self._getIceServerObject(srvid).delete()
@protectDjangoErrPage
def setSuperUserPassword(self, srvid, value):
self._getIceServerObject(srvid).setSuperuserPassword( value.encode( "UTF-8" ) )
@protectDjangoErrPage
def getConf(self, srvid, key):
if key == "username":
key = "playername";
return self._getIceServerObject(srvid).getConf( key )
@protectDjangoErrPage
def setConf(self, srvid, key, value):
if key == "username":
key = "playername";
if value is None:
value = ''
self._getIceServerObject(srvid).setConf( key, value.encode( "UTF-8" ) )
@protectDjangoErrPage
def registerPlayer(self, srvid, name, email, password):
mumbleid = self._getIceServerObject(srvid).registerPlayer( name.encode( "UTF-8" ) )
self.setRegistration( srvid, mumbleid, name, email, password );
return mumbleid;
@protectDjangoErrPage
def unregisterPlayer(self, srvid, mumbleid):
self._getIceServerObject(srvid).unregisterPlayer(mumbleid)
@protectDjangoErrPage
def getRegistration(self, srvid, mumbleid):
user = self._getIceServerObject(srvid).getRegistration(mumbleid)
return ObjectInfo(
userid = mumbleid,
name = user.name,
email = user.email,
pw = '',
);
@protectDjangoErrPage
def setRegistration(self, srvid, mumbleid, name, email, password):
import Murmur
user = Murmur.Player()
user.playerid = mumbleid;
user.name = name.encode( "UTF-8" )
user.email = email.encode( "UTF-8" )
user.pw = password.encode( "UTF-8" )
# update*r*egistration r is lowercase...
return self._getIceServerObject(srvid).updateregistration(user)
@protectDjangoErrPage
def getACL(self, srvid, channelid):
# need to convert acls to say "userid" instead of "playerid". meh.
raw_acls, raw_groups, raw_inherit = self._getIceServerObject(srvid).getACL(channelid)
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
def setACL(self, srvid, channelid, acls, groups, inherit):
import Murmur
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
def getTexture(self, srvid, mumbleid):
texture = self._getIceServerObject(srvid).getTexture(mumbleid)
if len(texture) == 0:
raise ValueError( "No Texture has been set." );
# this returns a list of bytes.
try:
decompressed = decompress( texture );
except error, err:
raise ValueError( err )
# iterate over 4 byte chunks of the string
imgdata = "";
for idx in range( 0, len(decompressed), 4 ):
# read 4 bytes = BGRA and convert to RGBA
# manual wrote getTexture returns "Textures are stored as zlib compress()ed 600x60 32-bit RGBA data."
# http://mumble.sourceforge.net/slice/Murmur/Server.html#getTexture
# but return values BGRA X(
bgra = unpack( "4B", decompressed[idx:idx+4] );
imgdata += pack( "4B", bgra[2], bgra[1], bgra[0], bgra[3] );
# return an 600x60 RGBA image object created from the data
return Image.fromstring( "RGBA", ( 600, 60 ), imgdata );
@protectDjangoErrPage
def setTexture(self, srvid, mumbleid, infile):
# open image, convert to RGBA, and resize to 600x60
img = infile.convert( "RGBA" ).transform( ( 600, 60 ), Image.EXTENT, ( 0, 0, 600, 60 ) );
# iterate over the list and pack everything into a string
bgrastring = "";
for ent in list( img.getdata() ):
# ent is in RGBA format, but Murmur wants BGRA (ARGB inverse), so stuff needs
# to be reordered when passed to pack()
bgrastring += pack( "4B", ent[2], ent[1], ent[0], ent[3] );
# compress using zlib
compressed = compress( bgrastring );
# pack the original length in 4 byte big endian, and concat the compressed
# data to it to emulate qCompress().
texture = pack( ">L", len(bgrastring) ) + compressed;
# finally call murmur and set the texture
self._getIceServerObject(srvid).setTexture(mumbleid, texture)
@protectDjangoErrPage
def verifyPassword(self, srvid, username, password):
return self._getIceServerObject(srvid).verifyPassword(username, password);
@staticmethod
def setUnicodeFlag(data):
ret = ''
if isinstance(data, tuple) or isinstance(data, list) or isinstance(data, dict):
ret = {}
for key in data.keys():
ret[MumbleCtlIce_118.setUnicodeFlag(key)] = MumbleCtlIce_118.setUnicodeFlag(data[key])
else:
ret = unicode(data, 'utf-8')
return ret
class MumbleCtlIce_120(MumbleCtlIce_118):
@protectDjangoErrPage
def getRegisteredPlayers(self, srvid, filter = ''):
users = self._getIceServerObject( srvid ).getRegisteredUsers( filter.encode( "UTF-8" ) )
ret = {};
for id in users:
ret[id] = ObjectInfo(
userid = id,
name = unicode( users[id], "utf8" ),
email = '',
pw = ''
);
return ret
@protectDjangoErrPage
def getPlayers(self, srvid):
userdata = self._getIceServerObject(srvid).getUsers();
for key in userdata:
if isinstance( userdata[key], str ):
userdata[key] = userdata[key].decode( "UTF-8" )
return userdata
@protectDjangoErrPage
def getState(self, srvid, sessionid):
userdata = self._getIceServerObject(srvid).getState(sessionid);
for key in userdata.__dict__:
attr = getattr( userdata, key )
if isinstance( attr, str ):
setattr( userdata, key, attr.decode( "UTF-8" ) )
return userdata
@protectDjangoErrPage
def registerPlayer(self, srvid, name, email, password):
# To get the real values of these ENUM entries, try
# Murmur.UserInfo.UserX.value
import Murmur
user = {
Murmur.UserInfo.UserName: name.encode( "UTF-8" ),
Murmur.UserInfo.UserEmail: email.encode( "UTF-8" ),
Murmur.UserInfo.UserPassword: password.encode( "UTF-8" ),
};
return self._getIceServerObject(srvid).registerUser( user );
@protectDjangoErrPage
def unregisterPlayer(self, srvid, mumbleid):
self._getIceServerObject(srvid).unregisterUser(mumbleid)
@protectDjangoErrPage
def getRegistration(self, srvid, mumbleid):
reg = self._getIceServerObject( srvid ).getRegistration( mumbleid )
user = ObjectInfo( userid=mumbleid, name="", email="", comment="", hash="", pw="" );
import Murmur
if Murmur.UserInfo.UserName in reg: user.name = reg[Murmur.UserInfo.UserName];
if Murmur.UserInfo.UserEmail in reg: user.email = reg[Murmur.UserInfo.UserEmail];
if Murmur.UserInfo.UserComment in reg: user.comment = reg[Murmur.UserInfo.UserComment];
if Murmur.UserInfo.UserHash in reg: user.hash = reg[Murmur.UserInfo.UserHash];
return user;
@protectDjangoErrPage
def setRegistration(self, srvid, mumbleid, name, email, password):
import Murmur
user = {
Murmur.UserInfo.UserName: name.encode( "UTF-8" ),
Murmur.UserInfo.UserEmail: email.encode( "UTF-8" ),
Murmur.UserInfo.UserPassword: password.encode( "UTF-8" ),
};
return self._getIceServerObject( srvid ).updateRegistration( mumbleid, user )
@protectDjangoErrPage
def getAllConf(self, srvid):
conf = self.setUnicodeFlag(self._getIceServerObject(srvid).getAllConf())
info = {};
for key in conf:
if key == "playername" and conf[key]:
# Buggy database transition from 1.1.8 -> 1.2.0
# Store username as "username" field and set playername field to empty
info['username'] = conf[key];
self.setConf( srvid, "playername", "" );
self.setConf( srvid, "username", conf[key] );
else:
info[str(key)] = conf[key];
return info;
@protectDjangoErrPage
def getConf(self, srvid, key):
return self._getIceServerObject(srvid).getConf( key )
@protectDjangoErrPage
def setConf(self, srvid, key, value):
if value is None:
value = ''
self._getIceServerObject(srvid).setConf( key, value.encode( "UTF-8" ) )
@protectDjangoErrPage
def getACL(self, srvid, channelid):
return self._getIceServerObject(srvid).getACL(channelid)
@protectDjangoErrPage
def setACL(self, srvid, channelid, acls, groups, inherit):
return self._getIceServerObject(srvid).setACL( channelid, acls, groups, inherit );
@protectDjangoErrPage
def getBans(self, srvid):
return self._getIceServerObject(srvid).getBans();
@protectDjangoErrPage
def setBans(self, srvid, bans):
return self._getIceServerObject(srvid).setBans(bans);
@protectDjangoErrPage
def addBanForSession(self, srvid, sessionid, **kwargs):
session = self.getState(srvid, sessionid);
if "bits" not in kwargs:
kwargs["bits"] = 128;
if "start" not in kwargs:
kwargs["start"] = int(time());
if "duration" not in kwargs:
kwargs["duration"] = 3600;
return self.addBan(srvid, address=session.address, **kwargs);
@protectDjangoErrPage
def addBan(self, srvid, **kwargs):
for key in kwargs:
if isinstance( kwargs[key], unicode ):
kwargs[key] = kwargs[key].encode("UTF-8")
from Murmur import Ban
srvbans = self.getBans(srvid);
srvbans.append( Ban( **kwargs ) );
return self.setBans(srvid, srvbans);
@protectDjangoErrPage
def kickUser(self, srvid, userid, reason=""):
return self._getIceServerObject(srvid).kickUser( userid, reason.encode("UTF-8") );
class MumbleCtlIce_122(MumbleCtlIce_120):
@protectDjangoErrPage
def getTexture(self, srvid, mumbleid):
raise ValueError( "This method is buggy in 1.2.2, sorry dude." );
@protectDjangoErrPage
def setTexture(self, srvid, mumbleid, infile):
buf = StringIO()
infile.save( buf, "PNG" )
buf.seek(0)
self._getIceServerObject(srvid).setTexture(mumbleid, buf.read())
class MumbleCtlIce_123(MumbleCtlIce_120):
@protectDjangoErrPage
def getRawTexture(self, srvid, mumbleid):
return self._getIceServerObject(srvid).getTexture(mumbleid)
@protectDjangoErrPage
def getTexture(self, srvid, mumbleid):
texture = self.getRawTexture(srvid, mumbleid)
if len(texture) == 0:
raise ValueError( "No Texture has been set." );
from StringIO import StringIO
try:
return Image.open( StringIO( texture ) )
except IOError, err:
raise ValueError( err )
@protectDjangoErrPage
def setTexture(self, srvid, mumbleid, infile):
buf = StringIO()
infile.save( buf, "PNG" )
buf.seek(0)
self._getIceServerObject(srvid).setTexture(mumbleid, buf.read())

View File

@@ -0,0 +1,164 @@
from sso.services import BaseService
from MumbleCtlIce import MumbleCtlIce
import Ice
class MumbleService(BaseService):
settings = { 'require_user': True,
'require_password': True,
'provide_login': False,
'use_auth_username': False,
'mumble_server_id': 2,
'name_format': r'%(alliance)s - %(corporation)s - %(name)s',
'connection_string': 'Meta:tcp -h 127.0.0.1 -p 6502',
'ice_file': 'Murmur.ice' }
def __init__(self):
try:
Ice.loadSlice(self.settings['ice_file'])
import Murmur
self.mur = Murmur
except:
pass
@property
def mumblectl(self):
if not hasattr(self, '_mumblectl'):
try:
self._mumblectl = MumbleCtlIce(self.settings['connection_string'], self.settings['ice_file'])
except:
self._mumblectl = None
return self._mumblectl
def add_user(self, username, password, **kwargs):
""" Add a user, returns a UID for that user """
details = { 'name': username,
'alliance': kwargs['character'].corporation.alliance.ticker,
'corporation': kwargs['character'].corporation.ticker }
username = self.settings['name_format'] % details
if self.raw_add_user(username, kwargs['user'].email, password):
self.update_groups(username, kwargs['user'].groups.all())
return { 'username': username, 'password': password }
else:
return False
def raw_add_user(self, username, email, password):
if self.mumblectl and self.mumblectl.registerPlayer(self.settings['mumble_server_id'], username, email, password):
return username
return False
def check_user(self, username):
""" Check if the username exists """
if self.mumblectl and len(self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], username)):
return True
return False
def delete_user(self, uid):
""" Delete a user by uid """
if self.mumblectl:
ids = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
if len(ids) > 0:
for accid in ids:
acc = ids[accid]
self.mumblectl.unregisterPlayer(self.settings['mumble_server_id'], acc['userid'])
return True
def disable_user(self, uid):
""" Disable a user by uid """
self.delete_user(uid)
return True
def enable_user(self, uid, password):
""" Enable a user by uid """
if self.mumblectl:
ids = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
if len(ids) > 0:
for accid in ids:
acc = ids[accid]
self.mumblectl.setRegistration(self.settings['mumble_server_id'], acc['userid'], acc['name'], acc['email'], password)
return True
else:
if self.raw_add_user(uid, '', password):
return True
return False
def set_user(self, uid, name = ''):
""" Set values ona user by uid """
if self.mumblectl:
ids = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
if len(ids) > 0:
for accid in ids:
acc = ids[accid]
self.mumblectl.setRegistration(self.settings['mumble_server_id'], acc['userid'], name, acc['email'], acc['pw'])
return True
return False
def reset_password(self, uid, password):
""" Reset the user's password """
return self.enable_user(uid, password)
def login(uid):
""" Login the user and provide cookies back """
pass
def _create_groups(self, groups):
""" Processes a list of groups and makes sure that related mumble groups exist """
acls = self.mumblectl.getACL(self.settings['mumble_server_id'], 0)
glist = []
for mgroup in acls[1]:
glist.append(mgroup.name)
newgroups = False
for agroup in groups:
if not str(agroup.name.replace(' ', '').lower()) in glist:
group = self.mur.Group()
group.name = str(agroup.name.replace(' ', '').lower())
group.members = []
group.add = []
group.remove = []
group.inheritable = True
group.inherit = True
group.inherited = False
acls[1].append(group)
newgroups = True
if newgroups:
self.mumblectl.setACL(self.settings['mumble_server_id'], 0, acls[0], acls[1], acls[2])
return acls
def update_groups(self, uid, groups, character=None):
""" Update the UID's groups based on the provided list """
user = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
if not user:
return False
user = user.values()[0]
acls = self._create_groups(groups)
#acls = self.mumblectl.getACL(self.settings['mumble_server_id'], 0)
for agroup in groups:
gid = 0
for mgroup in acls[1]:
if mgroup.name == agroup.name.replace(' ', '').lower():
if not user['userid'] in acls[1][gid].members:
acls[1][gid].add.append(user['userid'])
acls[1][gid].members.append(user['userid'])
else:
if user['userid'] in acls[1][gid].members:
acls[1][gid].remove.append(user['userid'])
acls[1][gid].remove.remove(user['userid'])
gid = gid + 1
self.mumblectl.setACL(self.settings['mumble_server_id'], 0, acls[0], acls[1], acls[2])
return True
ServiceClass = 'MumbleService'

View File

@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
"""
* Copyright © 2009, withgod <withgod@sourceforge.net>
* 2009-2010, Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
*
* Mumble-Django is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
"""
import re
class MumbleCtlBase(object):
""" This class defines the base interface that the Mumble model expects. """
cache = {};
@staticmethod
def newInstance( connstring, slicefile=None, icesecret=None ):
""" Create a new CTL object for the given connstring.
Optional parameters are the path to the slice file and the
Ice secret necessary to authenticate to Murmur.
The path can be omitted only if using DBus or running Murmur
1.2.3 or later, which exports a getSlice method to retrieve
the Slice from.
"""
# check cache
if connstring in MumbleCtlBase.cache:
return MumbleCtlBase.cache[connstring];
# connstring defines whether to connect via ICE or DBus.
# Dbus service names: some.words.divided.by.periods
# ICE specs are WAY more complex, so if DBus doesn't match, use ICE.
rd = re.compile( r'^(\w+\.)*\w+$' );
if rd.match( connstring ):
from MumbleCtlDbus import MumbleCtlDbus
ctl = MumbleCtlDbus( connstring )
else:
from MumbleCtlIce import MumbleCtlIce
ctl = MumbleCtlIce( connstring, slicefile, icesecret )
MumbleCtlBase.cache[connstring] = ctl;
return ctl;
@staticmethod
def clearCache():
MumbleCtlBase.cache = {};

View File

@@ -0,0 +1,98 @@
import hashlib
import random
from django.db import load_backend, transaction, IntegrityError
from sso.services import BaseDBService
import settings
class PhpBBService(BaseDBService):
"""
PHPBB Class, allows registration and sign-in
"""
settings = { 'require_user': False,
'require_password': False,
'provide_login': False,
'use_auth_username': False }
SQL_ADD_USER = r"INSERT INTO phpbb_users (username, username_clean, user_password, user_email) VALUES (%s, %s, %s, %s)"
SQL_DIS_USER = r"DELETE FROM phpbb_user_groups where user_id = (SELECT user_id FROM phpbb_user WHERE username = %s)"
SQL_CHECK_USER = r"SELECT username from phpbb_user WHERE username = %s"
SQL_ADD_USER_GROUP = r"INSERT INTO phpbb_user_group (group_id, user_id) VALUES (%s, %s)"
SQL_GET_GROUP = r"SELECT group_id from phpbb_groups WHERE group_name = %s"
SQL_ADD_GROUP = r"INSERT INTO phpbb_groups (group_name) VALUES (%s)"
def _gen_salt(self):
return "%x" % random.randint(0, 2147483647)
def _gen_hash(self, password, salt=None):
if not salt:
salt = self._gen_salt()
hash = hashlib.md5('%s-%s' % (salt, hashlib.md5(password).hexdigest())).hexdigest()
return ":B:%s:%s" % (salt, hash)
def add_user(self, username, password, **kwargs):
""" Add a user """
if 'user' in kwargs:
email = kwargs['user'].email
groups = kwargs['user'].groups.all()
else:
email = ''
pwhash = self._gen_hash(password)
self._dbcursor.execute(self.SQL_ADD_USER, [username, pwhash, email])
self.update_groups(username)
return { 'username': username, 'password': password }
def update_groups(self, username, groups, character=None):
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
row = self._dbcursor.fetchone()
user_id = row['user_id']
for group in groups:
self._dbcursor.execute(self.SQL_GET_GROUP, [group.name])
row = self._dbcursor.fetchone()
if not row:
self._dbcursor.execute(self.SQL_ADD_GROUP, [group.name])
self._dbcursor.execute(self.SQL_GET_GROUP, [group.name])
row = self._dbcursor.fetchone()
self._dbcursor.execute(self.SQL_ADD_USER_GROUP, [row['group_id'], user_id])
def check_user(self, username):
""" Check if the username exists """
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
row = self._dbcursor.fetchone()
if row:
return True
return False
def delete_user(self, uid):
""" Delete a user """
return True
def disable_user(self, uid):
""" Disable a user """
#self._dbcursor.execute(self.SQL_DIS_USER, [self._gen_user_token(), uid])
try:
self._dbcursor.execute(self.SQL_DIS_GROUP, [uid])
except IntegrityError:
# Record already exists, skip it
pass
return True
def enable_user(self, uid, password):
""" Enable a user """
pwhash = self._gen_mw_hash(password)
self._dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, uid])
self._dbcursor.execute(self.SQL_ENABLE_GROUP, [uid])
return True
def reset_password(self, uid, password):
""" Reset the user's password """
return self.enable_user(uid, password)
ServiceClass = 'PhpBBService'

View File

@@ -0,0 +1,77 @@
import hashlib
import random
from django.db import transaction, IntegrityError
from sso.services import BaseDBService
import settings
class POSTrackerService(BaseDBService):
"""
POS Tracker Class, allows registration.
"""
settings = { 'require_user': False,
'require_password': False,
'provide_login': False,
'use_auth_username': False,
'database_name': 'dreddit_pos' }
SQL_ADD_USER = r"INSERT INTO pos3_user (eve_id, name, pass, email, access, corp, alliance_id) VALUES (%s, %s, %s, %s, 1, %s, %s)"
SQL_DIS_USER = r"UPDATE pos3_user SET pass = '', away = 1 WHERE name = %s"
SQL_DEL_USER = r"DELETE FROM pos3_user WHERE name = %s"
SQL_ENABLE_USER = r"UPDATE pos3_user SET pass = %s, away = 0 WHERE name = %s"
SQL_CHECK_USER = r"SELECT name from pos3_user WHERE name = %s"
def _gen_salt(self):
return hashlib.md5("%x" % random.randint(0, 2147483647)).hexdigest()[:8]
def _gen_pwhash(self, password, salt=None):
if not salt:
salt = self._gen_salt()
pwhash = hashlib.md5("%s%s" % (salt, password)).hexdigest()
return (pwhash, salt)
def add_user(self, username, password, **kwargs):
""" Add a user """
email = kwargs['user'].email
pwhash, salt = self._gen_pwhash(password)
eveid = kwargs['character'].eveaccount_set.all()[0].api_user_id
corpname = kwargs['character'].corporation.name
if kwargs['character'].corporation and kwargs['character'].corporation.alliance:
allianceid = kwargs['character'].corporation.alliance.id
else:
allianceid = 0
self.dbcursor.execute(self.SQL_ADD_USER, [eveid, username, "%s%s" % (salt, pwhash) , email, corpname, allianceid])
return { 'username': username, 'password': password }
def check_user(self, username):
""" Check if the username exists """
self.dbcursor.execute(self.SQL_CHECK_USER, [username])
row = self.dbcursor.fetchone()
if row:
return True
return False
def delete_user(self, uid):
""" Delete a user """
self.dbcursor.execute(self.SQL_DEL_USER, [uid])
return True
def disable_user(self, uid):
""" Disable a user """
self.dbcursor.execute(self.SQL_DIS_USER, [uid])
return True
def enable_user(self, uid, password):
""" Enable a user """
pwhash, salt = self._gen_pwhash(password)
self.dbcursor.execute(self.SQL_ENABLE_USER, ["%s%s" % (salt, pwhash), uid])
return True
def reset_password(self, uid, password):
""" Reset the user's password """
return self.enable_user(uid, password)
ServiceClass = 'POSTrackerService'

View File

@@ -0,0 +1,70 @@
import hashlib
import random
from django.db import load_backend, transaction, IntegrityError
from sso.services import BaseDBService
import settings
class QMSService(BaseDBService):
"""
QMS Class, allows registration and sign-in
"""
settings = { 'require_user': False,
'require_password': False,
'provide_login': False,
'use_auth_username': False,
'database_name': 'dreddit_qms' }
SQL_ADD_USER = r"INSERT INTO users (ssoid, Name, passhash, salt, Email, certificate) VALUES (%s, %s, %s, %s, %s, %s)"
SQL_DIS_USER = r"UPDATE users SET passhash = '' WHERE ssoid = %s"
SQL_ENABLE_USER = r"UPDATE users SET passhash = %s, salt = %s, certificate = %s WHERE ssoid = %s"
SQL_CHECK_USER = r"SELECT ssoid from users WHERE ssoid = %s"
def _gen_salt(self):
return hashlib.md5("%x" % random.randint(0, 2147483647)).hexdigest()[:6]
def _gen_pwhash(self, password, salt=None):
if not salt:
salt = self._gen_salt()
pwhash = hashlib.md5(password).hexdigest()
cert = hashlib.md5('%s%s' % (pwhash, salt)).hexdigest()
return (pwhash, salt, cert)
def add_user(self, username, password, **kwargs):
""" Add a user """
email = kwargs['user'].email
pwhash, salt, cert = self._gen_pwhash(password)
self.dbcursor.execute(self.SQL_ADD_USER, [username, username, pwhash, salt, email, cert])
return { 'username': username, 'password': password }
def check_user(self, username):
""" Check if the username exists """
self.dbcursor.execute(self.SQL_CHECK_USER, [username])
row = self.dbcursor.fetchone()
if row:
return True
return False
def delete_user(self, uid):
""" Delete a user """
#self.dbcursor.execute(self.SQL_DEL_REV, [uid])
#self.dbcursor.execute(self.SQL_DEL_USER, [uid])
return True
def disable_user(self, uid):
""" Disable a user """
self.dbcursor.execute(self.SQL_DIS_USER, [uid])
return True
def enable_user(self, uid, password):
""" Enable a user """
pwhash, salt, cert = self._gen_pwhash(password)
self.dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, salt, cert, uid])
return True
def reset_password(self, uid, password):
""" Reset the user's password """
return self.enable_user(uid, password)
ServiceClass = 'QMSService'

View File

@@ -0,0 +1,78 @@
import hashlib
import random
from sso.services import BaseDBService
import settings
class SMFService(BaseDBService):
"""
SMF Class, allows registration and sign-in
"""
settings = { 'require_user': True,
'require_password': True,
'provide_login': False,
'use_auth_username': False
'can_delete': False }
SQL_ADD_USER = r"INSERT INTO phpbb_users (username, username_clean, user_password, user_email) VALUES (%s, %s, %s, %s)"
SQL_DIS_USER = r"DELETE FROM phpbb_user_groups where user_id = (SELECT user_id FROM phpbb_user WHERE username = %s)"
SQL_CHECK_USER = r"SELECT username from phpbb_user WHERE username = %s"
SQL_ADD_USER_GROUP = r"INSERT INTO phpbb_user_group (group_id, user_id) VALUES (%s, %s)"
SQL_GET_GROUP = r"SELECT group_id from phpbb_groups WHERE group_name = %s"
SQL_ADD_GROUP = r"INSERT INTO phpbb_groups (group_name) VALUES (%s)"
def _gen_salt(self):
return "%x" % random.randint(0, 2147483647)
def _gen_hash(self, password, salt=None):
if not salt:
salt = self._gen_salt()
hash = hashlib.md5('%s-%s' % (salt, hashlib.md5(password).hexdigest())).hexdigest()
return ":B:%s:%s" % (salt, hash)
def add_user(self, username, password, **kwargs):
""" Add a user """
if 'user' in kwargs:
email = kwargs['user'].email
else:
email = ''
pwhash = self._gen_hash(password)
self._dbcursor.execute(self.SQL_ADD_USER, [username, pwhash, email])
self.update_groups(username)
return { 'username': username, 'password': password }
def update_groups(self, username, groups, character=None):
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
row = self._dbcursor.fetchone()
user_id = row['id_member']
smfgrps = self._get_smf_groups()
grpids = []
for group in groups:
if group.name in smfgrps:
grpids.append(smfgrps[group.name])
else:
grpids.append(self._create_smf_group(group.name))
# Update DB with grouplist
self._dbcursor.execute(self.SQL_UPDATE_GROUPS, [user_id, ','.join(groupids)])
def check_user(self, username):
""" Check if the username exists """
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
row = self._dbcursor.fetchone()
if row:
return True
return False
def reset_password(self, uid, password):
""" Reset the user's password """
return self.enable_user(uid, password)
ServiceClass = 'SMFService'

View File

@@ -0,0 +1,195 @@
import urllib
from sso.services import BaseService
from ts3 import TS3Server
class TS3Service(BaseService):
settings = { 'require_user': True,
'require_password': False,
'provide_login': False,
'use_auth_username': False,
'host': 'mumble.pleaseignore.com',
'port': 10011,
'sa_login': 'serveradmin',
'sa_password': '',
'vhost_id': 0,
'authed_sgid': 12,
'name_format': '%(alliance)s - %(corporation)s - %(name)s',
'bookmark_name': 'TEST Alliance TS3',
'ignore_groups': [6]}
def __init__(self):
pass
@property
def conn(self):
if not hasattr(self, '_conn'):
self._conn = TS3Server(self.settings['host'], self.settings['port'])
self._conn.login(self.settings['sa_login'], self.settings['sa_password'])
self._conn.use(self.settings['vhost_id'])
return self._conn
def add_user(self, username, password, **kwargs):
""" Add a user, returns a UID for that user """
details = { 'name': username,
'corporation': kwargs['character'].corporation.ticker }
if kwargs['character'].corporation.alliance:
details['alliance'] = kwargs['character'].corporation.alliance.ticker
else:
details['alliance'] = None
username = self.settings['name_format'] % details
ret = self.conn.send_command('tokenadd', {'tokentype': 0, 'tokenid1': self.settings['authed_sgid'], 'tokenid2': 0, 'tokendescription': kwargs['character'].name.replace(' ', ''), 'tokencustomset': "ident=sso_uid value=%s|ident=sso_userid value=%s|ident=eve_charid value=%s" % (kwargs['character'].name.replace(' ', ''), kwargs['user'].id, kwargs['character'].id) })
if 'keys' in ret and 'token' in ret['keys']:
token = ret['keys']['token']
url = "<a href='ts3server://%s?token=%s'>Click this link to connect and register on TS3</a>" % (self.settings['host'], token)
return { 'username': kwargs['character'].name.replace(' ', ''), 'display name': username, 'permission token': token, 'registration url': url }
return None
def check_user(self, uid):
""" Check if the username exists """
# Lookup user using customsearch with sso_uid=uid
return self._get_userid(uid)
def delete_user(self, uid):
""" Delete a user by uid """
user = self._get_userid(uid)
if user:
for client in self.conn.send_command('clientlist'):
if client['keys']['client_database_id'] == user:
self.conn.send_command('clientkick', {'clid': client['keys']['clid'], 'reasonid': 5, 'reasonmsg': 'Auth service deleted'})
ret = self.conn.send_command('clientdbdelete', {'cldbid': user })
if ret == '0':
return True
else:
return True
def disable_user(self, uid):
""" Disable a user by uid """
user = self._get_userid(uid)
if user:
ret = self.conn.send_command('servergroupdelclient', {'sgid': self.settings['authed_sgid'], 'cldbid': user })
if ret == '0':
groups = self._user_group_list(user)
for group in groups:
self.conn.send_command('servergroupdelclient', {'sgid': groups[group], 'cldbid': user })
return True
return False
def enable_user(self, uid, password):
""" Enable a user by uid """
user = self._get_userid(uid)
if user:
ret = self.conn.send_command('servergroupaddclient', {'sgid': self.settings['authed_sgid'], 'cldbid': user })
if ret == '0':
return True
def reset_password(self, uid, password):
""" Reset the user's password """
pass
def login(uid):
""" Login the user and provide cookies back """
pass
def _group_by_name(self, groupname):
if not hasattr(self, '__group_cache') or not self.__group_cache:
self.__group_cache = self.conn.send_command('servergrouplist')
for group in self.__group_cache:
if group['keys']['name'] == groupname:
return group['keys']['sgid']
return None
def _get_userid(self, uid):
""" Finds the TS3 ID of a user from their UID """
ret = self.conn.send_command('customsearch', {'ident': 'sso_uid', 'pattern': uid})
if ret and 'keys' in ret and 'cldbid' in ret['keys']:
return ret['keys']['cldbid']
def _create_group(self, groupname):
""" Creates a Server Group and returns the SGID """
sgid = self._group_by_name(groupname)
if not sgid:
ret = self.conn.send_command('servergroupadd', { 'name': groupname })
self.__group_cache = None
sgid = ret['keys']['sgid']
self.conn.send_command('servergroupaddperm', { 'sgid': sgid, 'permsid': 'i_group_needed_modify_power', 'permvalue': 75, 'permnegated': 0, 'permskip': 0 })
self.conn.send_command('servergroupaddperm', { 'sgid': sgid, 'permsid': 'i_group_needed_member_add_power', 'permvalue': 100, 'permnegated': 0, 'permskip': 0 })
self.conn.send_command('servergroupaddperm', { 'sgid': sgid, 'permsid': 'i_group_needed_member_remove_power', 'permvalue': 100, 'permnegated': 0, 'permskip': 0 })
return sgid
def _group_list(self):
""" List of all groups on the TS server """
if not hasattr(self, '__group_cache') or not self.__group_cache:
self.__group_cache = self.conn.send_command('servergrouplist')
outlist = {}
for group in self.__group_cache:
outlist[group['keys']['name']] = group['keys']['sgid']
return outlist
def _user_group_list(self, cldbid):
""" List of all groups assigned to a user """
groups = self.conn.send_command('servergroupsbyclientid', {'cldbid': cldbid })
outlist = {}
if type(groups) == list:
for group in groups:
outlist[group['keys']['name']] = group['keys']['sgid']
elif type(groups) == dict:
outlist[groups['keys']['name']] = groups['keys']['sgid']
return outlist
def update_groups(self, uid, groups, character=None):
""" Update the UID's groups based on the provided list """
cldbid = self._get_userid(uid)
if cldbid:
tsgrplist = self._group_list()
usrgrplist = self._user_group_list(cldbid)
# Add groups
if groups.count():
for g in groups:
if not g.name in tsgrplist:
tsgrplist[g.name] = self._create_group(g.name)
if not g.name in usrgrplist:
self.conn.send_command('servergroupaddclient', {'sgid': tsgrplist[g.name], 'cldbid': cldbid })
usrgrplist[g.name] = tsgrplist[g.name]
# Add to corporation groups
if character and character.corporation:
if character.corporation.ticker in usrgrplist:
del usrgrplist[character.corporation.ticker]
else:
if not character.corporation.ticker in tsgrplist:
tsgrplist[character.corporation.ticker] = self._create_group(character.corporation.ticker)
self.conn.send_command('servergroupaddclient', {'sgid': tsgrplist[character.corporation.ticker], 'cldbid': cldbid })
# Remove OKed groups from the delete list
for g in groups:
if g.name in usrgrplist:
del usrgrplist[g.name]
# Remove ignored and admin groups
for k, v in usrgrplist.items():
if not int(v) == self.settings['authed_sgid'] and not int(v) in self.settings['ignore_groups']:
self.conn.send_command('servergroupdelclient', {'sgid': v, 'cldbid': cldbid })
return True
ServiceClass = 'TS3Service'

257
app/sso/services/ts3/ts3.py Normal file
View File

@@ -0,0 +1,257 @@
import time
import socket
import logging
class ConnectionError():
def __init__(self, ip, port):
self.ip = ip
self.port = port
def __str__():
return 'Error connecting to host %s port %s' % (self.ip, self.port)
ts3_escape = { '/': r"\/",
' ': r'\s',
'|': r'\p',
"\a": r'\a',
"\b": r'\b',
"\f": r'\f',
"\n": r'\n',
"\r": r'\r',
"\t": r'\t',
"\v": r'\v' }
class TS3Proto():
bytesin = 0
bytesout = 0
_connected = False
def __init__(self):
self._log = logging.getLogger('%s.%s' % (__name__, self.__class__.__name__))
pass
def connect(self, ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
except:
#raise ConnectionError(ip, port)
raise
else:
self._sock = s
self._sockfile = s.makefile('r', 0)
data = self._sockfile.readline()
if data.strip() == "TS3":
self._sockfile.readline()
self._connected = True
return True
def disconnect(self):
self.send_command("quit")
self._sock.close()
self._sock = None
self._connected = False
self._log.info('Disconnected')
def send_command(self, command, keys=None, opts=None):
cmd = self.construct_command(command, keys=keys, opts=opts)
self.send('%s\n' % cmd)
data = []
while True:
resp = self._sockfile.readline()
resp = self.parse_command(resp)
if not 'command' in resp:
data.append(resp)
else:
break
if resp['command'] == 'error':
if data and resp['keys']['id'] == '0':
if len(data) > 1:
return data
else:
return data[0]
else:
return resp['keys']['id']
def construct_command(self, command, keys=None, opts=None):
"""
Constructs a TS3 formatted command string
Keys can have a single nested list to construct a nested parameter
@param command: Command list
@type command: string
@param keys: Key/Value pairs
@type keys: dict
@param opts: Options
@type opts: list
"""
cstr = [command]
# Add the keys and values, escape as needed
if keys:
for key in keys:
if isinstance(keys[key], list):
ncstr = []
for nest in keys[key]:
ncstr.append("%s=%s" % (key, self._escape_str(nest)))
cstr.append("|".join(ncstr))
else:
cstr.append("%s=%s" % (key, self._escape_str(keys[key])))
# Add in options
if opts:
for opt in opts:
cstr.append("-%s" % opt)
return " ".join(cstr)
def parse_command(self, commandstr):
"""
Parses a TS3 command string into command/keys/opts tuple
@param commandstr: Command string
@type commandstr: string
"""
if len(commandstr.split('|')) > 1:
vals = []
for cmd in commandstr.split('|'):
vals.append(self.parse_command(cmd))
return vals
cmdlist = commandstr.strip().split(' ')
command = None
keys = {}
opts = []
for key in cmdlist:
v = key.strip().split('=')
if len(v) > 1:
# Key
if len > 2:
# Fix the stupidities in TS3 escaping
v = [v[0], '='.join(v[1:])]
key, value = v
keys[key] = self._unescape_str(value)
elif v[0][0] == '-':
# Option
opts.append(v[0][1:])
else:
command = v[0]
d = {'keys': keys, 'opts': opts}
if command:
d['command'] = command
return d
@staticmethod
def _escape_str(value):
"""
Escape a value into a TS3 compatible string
@param value: Value
@type value: string/int
"""
if isinstance(value, int): return "%d" % value
value = value.replace("\\", r'\\')
for i, j in ts3_escape.iteritems():
value = value.replace(i, j)
return value
@staticmethod
def _unescape_str(value):
"""
Unescape a TS3 compatible string into a normal string
@param value: Value
@type value: string/int
"""
if isinstance(value, int): return "%d" % value
value = value.replace(r"\\", "\\")
for i, j in ts3_escape.iteritems():
value = value.replace(j, i)
return value
def send(self, payload):
if self._connected:
self._log.debug('Sent: %s' % payload)
self._sockfile.write(payload)
class TS3Server(TS3Proto):
def __init__(self, ip, port, id=0, sock=None):
"""
Abstraction class for TS3 Servers
@param ip: IP Address
@type ip: str
@param port: Port Number
@type port: int
"""
TS3Proto.__init__(self)
if not sock:
if self.connect(ip, port) and id > 0:
self.use(id)
else:
self._sock = sock
self._sockfile = sock.makefile('r', 0)
self._connected = True
def login(self, username, password):
"""
Login to the TS3 Server
@param username: Username
@type username: str
@param password: Password
@type password: str
"""
d = self.send_command('login', keys={'client_login_name': username, 'client_login_password': password })
if d == 0:
self._log.info('Login Successful')
return True
return False
def serverlist(self):
"""
Get a list of all Virtual Servers on the connected TS3 instance
"""
if self._connected:
return self.send_command('serverlist')
def gm(self, msg):
"""
Send a global message to the current Virtual Server
@param msg: Message
@type ip: str
"""
if self._connected:
return self.send_command('gm', keys={'msg': msg})
def use(self, id):
"""
Use a particular Virtual Server instance
@param id: Virtual Server ID
@type id: int
"""
if self._connected and id > 0:
self.send_command('use', keys={'sid': id})

View File

@@ -0,0 +1,95 @@
import hashlib
import random
from django.db import load_backend, transaction, IntegrityError
from sso.services import BaseDBService
import settings
class MediawikiService(BaseDBService):
"""
Mediawiki Class, allows registration and sign-in
"""
settings = { 'require_user': False,
'require_password': False,
'provide_login': False,
'use_auth_username': False,
'database_name': 'dreddit_wiki' }
default_options = 'rows=80\ncols=50'
SQL_ADD_USER = r"INSERT INTO user (user_name, user_password, user_newpassword, user_email, user_options) VALUES (%s, %s, '', %s, %s)"
SQL_DIS_USER = r"UPDATE user SET user_password = '', user_email = '', user_token = %s WHERE user_name = %s"
SQL_DIS_GROUP = r"INSERT INTO user_groups (ug_user, ug_group) VALUES ((SELECT user_id FROM user WHERE user_name = %s), 'Disabled')"
SQL_ENABLE_USER = r"UPDATE user SET user_password = %s WHERE user_name = %s"
SQL_ENABLE_GROUP = r"DELETE FROM user_groups where ug_user = (SELECT user_id FROM user WHERE user_name = %s) AND ug_group = 'Disabled'"
SQL_CHECK_USER = r"SELECT user_name from user WHERE user_name = %s"
SQL_DEL_REV = r"UPDATE revision SET rev_user = (SELECT user_id FROM user WHERE user_name = 'DeletedUser'), rev_user_text = 'DeletedUser' WHERE rev_user = (SELECT user_id FROM user WHERE user_name = %s)"
SQL_DEL_USER = r"DELETE FROM user WHERE user_name = %s"
def _gen_salt(self):
return "%x" % random.randint(0, 2147483647)
def _gen_mw_hash(self, password, salt=None):
if not salt:
salt = self._gen_salt()
hash = hashlib.md5('%s-%s' % (salt, hashlib.md5(password).hexdigest())).hexdigest()
return ":B:%s:%s" % (salt, hash)
def _gen_user_token(self):
hash = hashlib.md5(self._gen_salt()).hexdigest()
return hash
def _clean_username(self, username):
username = username.strip()
return username[0].upper() + username[1:]
def add_user(self, username, password, **kwargs):
""" Add a user """
if 'user' in kwargs:
email = kwargs['user'].email
else:
email = ''
pwhash = self._gen_mw_hash(password)
self.dbcursor.execute(self.SQL_ADD_USER, [self._clean_username(username), pwhash, email, self.default_options])
return { 'username': self._clean_username(username), 'password': password }
def check_user(self, username):
""" Check if the username exists """
self.dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
row = self.dbcursor.fetchone()
if row:
return True
return False
def delete_user(self, uid):
""" Delete a user """
self.dbcursor.execute(self.SQL_DEL_REV, [uid])
self.dbcursor.execute(self.SQL_DEL_USER, [uid])
return True
def disable_user(self, uid):
""" Disable a user """
#self.dbcursor.execute(self.SQL_DIS_USER, [self._gen_user_token(), uid])
try:
self.dbcursor.execute(self.SQL_DIS_GROUP, [uid])
except IntegrityError:
# Record already exists, skip it
pass
return True
def enable_user(self, uid, password):
""" Enable a user """
pwhash = self._gen_mw_hash(password)
self.dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, uid])
self.dbcursor.execute(self.SQL_ENABLE_GROUP, [uid])
return True
def reset_password(self, uid, password):
""" Reset the user's password """
return self.enable_user(uid, password)
ServiceClass = 'MediawikiService'