mirror of
https://github.com/nikdoof/test-auth.git
synced 2025-12-14 06:42:16 +00:00
Reorganise the file structure into a project tree
This commit is contained in:
84
app/sso/services/__init__.py
Normal file
84
app/sso/services/__init__.py
Normal 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
|
||||
|
||||
8
app/sso/services/dummy/__init__.py
Normal file
8
app/sso/services/dummy/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from sso.services import BaseService
|
||||
|
||||
class DummyService(BaseService):
|
||||
""" Always passes, good for a test service """
|
||||
pass
|
||||
|
||||
|
||||
ServiceClass = 'DummyService'
|
||||
87
app/sso/services/ipb/__init__.py
Normal file
87
app/sso/services/ipb/__init__.py
Normal 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'
|
||||
151
app/sso/services/jabber/__init__.py
Normal file
151
app/sso/services/jabber/__init__.py
Normal 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'
|
||||
86
app/sso/services/miningbuddy/__init__.py
Normal file
86
app/sso/services/miningbuddy/__init__.py
Normal 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'
|
||||
610
app/sso/services/mumble/MumbleCtlIce.py
Normal file
610
app/sso/services/mumble/MumbleCtlIce.py
Normal 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())
|
||||
|
||||
|
||||
164
app/sso/services/mumble/__init__.py
Normal file
164
app/sso/services/mumble/__init__.py
Normal 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'
|
||||
58
app/sso/services/mumble/mctl.py
Normal file
58
app/sso/services/mumble/mctl.py
Normal 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 = {};
|
||||
98
app/sso/services/phpbb/__init__.py
Normal file
98
app/sso/services/phpbb/__init__.py
Normal 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'
|
||||
77
app/sso/services/postracker/__init__.py
Normal file
77
app/sso/services/postracker/__init__.py
Normal 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'
|
||||
70
app/sso/services/qms/__init__.py
Normal file
70
app/sso/services/qms/__init__.py
Normal 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'
|
||||
78
app/sso/services/smf/__init__.py
Normal file
78
app/sso/services/smf/__init__.py
Normal 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'
|
||||
195
app/sso/services/ts3/__init__.py
Normal file
195
app/sso/services/ts3/__init__.py
Normal 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
257
app/sso/services/ts3/ts3.py
Normal 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})
|
||||
95
app/sso/services/wiki/__init__.py
Normal file
95
app/sso/services/wiki/__init__.py
Normal 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'
|
||||
Reference in New Issue
Block a user