From 1670eee9eb3bbbf6db708955f56e544b869516bf Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Thu, 3 Mar 2011 10:45:55 +0000 Subject: [PATCH] Allow services to specify to use the charnames or auth username, also add IPB and SMF framework --- sso/services/ipb/__init__.py | 87 ++++++++++++++++++++++++++++ sso/services/jabber/__init__.py | 1 + sso/services/miningbuddy/__init__.py | 1 + sso/services/mumble/__init__.py | 1 + sso/services/phpbb/__init__.py | 3 +- sso/services/postracker/__init__.py | 1 + sso/services/qms/__init__.py | 1 + sso/services/smf/__init__.py | 78 +++++++++++++++++++++++++ sso/services/ts3/__init__.py | 1 + sso/services/wiki/__init__.py | 1 + sso/views.py | 7 ++- 11 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 sso/services/ipb/__init__.py create mode 100644 sso/services/smf/__init__.py diff --git a/sso/services/ipb/__init__.py b/sso/services/ipb/__init__.py new file mode 100644 index 0000000..9c889c4 --- /dev/null +++ b/sso/services/ipb/__init__.py @@ -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' diff --git a/sso/services/jabber/__init__.py b/sso/services/jabber/__init__.py index 5909455..c458d39 100644 --- a/sso/services/jabber/__init__.py +++ b/sso/services/jabber/__init__.py @@ -8,6 +8,7 @@ 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'} diff --git a/sso/services/miningbuddy/__init__.py b/sso/services/miningbuddy/__init__.py index ff10349..8f2ab42 100644 --- a/sso/services/miningbuddy/__init__.py +++ b/sso/services/miningbuddy/__init__.py @@ -14,6 +14,7 @@ class MiningBuddyService(BaseDBService): settings = { 'require_user': False, 'require_password': False, 'provide_login': False, + 'use_auth_username': False, 'database_name': 'dreddit_mining', 'password_salt': 's98ss7fsc7fd2rf62ctcrlwztstnzve9toezexcsdhfgviuinusxcdtsvbrg' } diff --git a/sso/services/mumble/__init__.py b/sso/services/mumble/__init__.py index fbb1769..74142ca 100644 --- a/sso/services/mumble/__init__.py +++ b/sso/services/mumble/__init__.py @@ -7,6 +7,7 @@ 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', diff --git a/sso/services/phpbb/__init__.py b/sso/services/phpbb/__init__.py index dfd7e36..67b8372 100644 --- a/sso/services/phpbb/__init__.py +++ b/sso/services/phpbb/__init__.py @@ -12,7 +12,8 @@ class PhpBBService(BaseDBService): settings = { 'require_user': False, 'require_password': False, - 'provide_login': 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)" diff --git a/sso/services/postracker/__init__.py b/sso/services/postracker/__init__.py index 185f7c0..6b1b875 100644 --- a/sso/services/postracker/__init__.py +++ b/sso/services/postracker/__init__.py @@ -13,6 +13,7 @@ class POSTrackerService(BaseDBService): 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)" diff --git a/sso/services/qms/__init__.py b/sso/services/qms/__init__.py index ef88051..eb5057a 100644 --- a/sso/services/qms/__init__.py +++ b/sso/services/qms/__init__.py @@ -13,6 +13,7 @@ class QMSService(BaseDBService): 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)" diff --git a/sso/services/smf/__init__.py b/sso/services/smf/__init__.py new file mode 100644 index 0000000..3fa8f2a --- /dev/null +++ b/sso/services/smf/__init__.py @@ -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' diff --git a/sso/services/ts3/__init__.py b/sso/services/ts3/__init__.py index 3152d32..a1d45f8 100644 --- a/sso/services/ts3/__init__.py +++ b/sso/services/ts3/__init__.py @@ -7,6 +7,7 @@ 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', diff --git a/sso/services/wiki/__init__.py b/sso/services/wiki/__init__.py index d9b8f8c..978d203 100644 --- a/sso/services/wiki/__init__.py +++ b/sso/services/wiki/__init__.py @@ -13,6 +13,7 @@ class MediawikiService(BaseDBService): settings = { 'require_user': False, 'require_password': False, 'provide_login': False, + 'use_auth_username': False, 'database_name': 'dreddit_wiki' } default_options = 'rows=80\ncols=50' diff --git a/sso/views.py b/sso/views.py index 3084cbc..b8f1fa5 100644 --- a/sso/views.py +++ b/sso/views.py @@ -59,8 +59,11 @@ def service_add(request): else: acc.password = None - # Decode unicode and remove invalid characters - username = re.sub('[^a-zA-Z0-9_-]+', '', unicodedata.normalize('NFKD', acc.character.name).encode('ASCII', 'ignore')) + if acc.service.settings['use_auth_username']: + username = request.user.username + else: + # Decode unicode and remove invalid characters + username = re.sub('[^a-zA-Z0-9_-]+', '', unicodedata.normalize('NFKD', acc.character.name).encode('ASCII', 'ignore')) if acc.service.api_class.check_user(username): error = "Username already exists on the target service, please contact an admin."