diff --git a/allianceauth/services/modules/smf/manager.py b/allianceauth/services/modules/smf/manager.py index e4f52569..3293c8d3 100644 --- a/allianceauth/services/modules/smf/manager.py +++ b/allianceauth/services/modules/smf/manager.py @@ -6,6 +6,8 @@ import hashlib import logging import re +from packaging import version + from django.db import connections from django.conf import settings from allianceauth.eveonline.models import EveCharacter @@ -20,9 +22,18 @@ class SmfManager: def __init__(self): pass - SQL_ADD_USER = r"INSERT INTO %smembers (member_name, passwd, email_address, date_registered, real_name," \ - r" buddy_list, message_labels, openid_uri, signature, ignore_boards) " \ - r"VALUES (%%s, %%s, %%s, %%s, %%s, 0, 0, 0, 0, 0)" % TABLE_PREFIX + # For SMF < 2.1 + SQL_ADD_USER_SMF_20 = r"INSERT INTO %smembers (member_name, passwd, email_address, date_registered, real_name," \ + r" buddy_list, message_labels, openid_uri, signature, ignore_boards) " \ + r"VALUES (%%s, %%s, %%s, %%s, %%s, 0, 0, 0, 0, 0)" % TABLE_PREFIX + + # For SMF >= 2.1 + SQL_ADD_USER_SMF_21 = r"INSERT INTO %smembers (member_name, passwd, email_address, date_registered, real_name," \ + r" buddy_list, signature, ignore_boards) " \ + r"VALUES (%%s, %%s, %%s, %%s, %%s, 0, 0, 0)" % TABLE_PREFIX + + # returns something like »window.smfVersion = "SMF 2.0.19";« + SQL_GET_CURRENT_SMF_VERSION = r"SELECT data FROM %sadmin_info_files WHERE filename = %%s" % TABLE_PREFIX SQL_DEL_USER = r"DELETE FROM %smembers where member_name = %%s" % TABLE_PREFIX @@ -46,6 +57,26 @@ class SmfManager: SQL_ADD_USER_AVATAR = r"UPDATE %smembers SET avatar = %%s WHERE id_member = %%s" % TABLE_PREFIX + @classmethod + def _get_current_smf_version(cls) -> str: + """ + Get the current SMF version from the DB + :return: + """ + + cursor = connections['smf'].cursor() + cursor.execute(cls.SQL_GET_CURRENT_SMF_VERSION, ['current-version.js']) + row = cursor.fetchone() + db_result = row[0] + + pattern = re.compile(r"\d+(\.\d+)+") + result = pattern.search(db_result) + + smf_version = result.group(0) + + return smf_version + + @staticmethod def _sanitize_groupname(name): name = name.strip(' _') @@ -73,15 +104,15 @@ class SmfManager: @classmethod def create_group(cls, groupname): - logger.debug("Creating smf group %s" % groupname) + logger.debug(f"Creating smf group {groupname}") cursor = connections['smf'].cursor() cursor.execute(cls.SQL_ADD_GROUP, [groupname, groupname]) - logger.info("Created smf group %s" % groupname) + logger.info(f"Created smf group {groupname}") return cls.get_group_id(groupname) @classmethod def get_group_id(cls, groupname): - logger.debug("Getting smf group id for groupname %s" % groupname) + logger.debug(f"Getting smf group id for groupname {groupname}") cursor = connections['smf'].cursor() cursor.execute(cls.SQL_GET_GROUP_ID, [groupname]) row = cursor.fetchone() @@ -90,14 +121,14 @@ class SmfManager: @classmethod def check_user(cls, username): - logger.debug("Checking smf username %s" % username) + logger.debug(f"Checking smf username {username}") cursor = connections['smf'].cursor() cursor.execute(cls.SQL_USER_ID_FROM_USERNAME, [cls.santatize_username(username)]) row = cursor.fetchone() if row: - logger.debug("Found user %s on smf" % username) + logger.debug(f"Found user {username} on smf") return True - logger.debug("User %s not found on smf" % username) + logger.debug(f"User {username} not found on smf") return False @classmethod @@ -110,7 +141,7 @@ class SmfManager: @classmethod def get_user_id(cls, username): - logger.debug("Getting smf user id for username %s" % username) + logger.debug(f"Getting smf user id for username {username}") cursor = connections['smf'].cursor() cursor.execute(cls.SQL_USER_ID_FROM_USERNAME, [username]) row = cursor.fetchone() @@ -118,7 +149,7 @@ class SmfManager: logger.debug(f"Got smf user id {row[0]} for username {username}") return row[0] else: - logger.error("username %s not found on smf. Unable to determine user id ." % username) + logger.error(f"username {username} not found on smf. Unable to determine user id .") return None @classmethod @@ -130,12 +161,12 @@ class SmfManager: out = {} for row in rows: out[row[1]] = row[0] - logger.debug("Got smf groups %s" % out) + logger.debug(f"Got smf groups {out}") return out @classmethod def get_user_groups(cls, userid): - logger.debug("Getting smf user id %s groups" % userid) + logger.debug(f"Getting smf user id {userid} groups") cursor = connections['smf'].cursor() cursor.execute(cls.SQL_GET_USER_GROUPS, [userid]) out = [row[0] for row in cursor.fetchall()] @@ -144,8 +175,11 @@ class SmfManager: @classmethod def add_user(cls, username, email_address, groups, characterid): - logger.debug("Adding smf user with member_name {}, email_address {}, characterid {}".format( - username, email_address, characterid)) + logger.debug( + f"Adding smf user with member_name {username}, " + f"email_address {email_address}, " + f"characterid {characterid}" + ) cursor = connections['smf'].cursor() username_clean = cls.santatize_username(username) passwd = cls.generate_random_pass() @@ -154,42 +188,59 @@ class SmfManager: register_date = cls.get_current_utc_date() # check if the username was simply revoked if cls.check_user(username) is True: - logger.warn("Unable to add smf user with username %s - already exists. Updating user instead." % username) + logger.warning(f"Unable to add smf user with username {username} - already exists. Updating user instead.") cls.__update_user_info(username_clean, email_address, pwhash) else: try: - cursor.execute(cls.SQL_ADD_USER, - [username_clean, passwd, email_address, register_date, username_clean]) + smf_version = cls._get_current_smf_version() + + if version.parse(smf_version) < version.parse("2.1"): + logger.debug("SMF compatibility: < 2.1") + + cursor.execute( + cls.SQL_ADD_USER_SMF_20, + [username_clean, pwhash, email_address, register_date, username_clean] + ) + else: + logger.debug("SMF compatibility: >= 2.1") + + cursor.execute( + cls.SQL_ADD_USER_SMF_21, + [username_clean, pwhash, email_address, register_date, username_clean] + ) cls.add_avatar(username_clean, characterid) - logger.info("Added smf member_name %s" % username_clean) + logger.info(f"Added smf member_name {username_clean}") cls.update_groups(username_clean, groups) - except: - logger.warn("Unable to add smf user %s" % username_clean) + except Exception as e: + logger.warning(f"Unable to add smf user {username_clean}: {e}") pass return username_clean, passwd @classmethod def __update_user_info(cls, username, email_address, passwd): logger.debug( - f"Updating smf user {username} info: username {email_address} password of length {len(passwd)}") + f"Updating smf user {username} info: " + f"username {email_address} " + f"password of length {len(passwd)}" + ) cursor = connections['smf'].cursor() try: cursor.execute(cls.SQL_DIS_USER, [email_address, passwd, username]) - logger.info("Updated smf user %s info" % username) - except: - logger.exception("Unable to update smf user %s info." % username) + logger.info(f"Updated smf user {username} info") + except Exception as e: + logger.exception(f"Unable to update smf user {username} info. ({e})") pass @classmethod def delete_user(cls, username): - logger.debug("Deleting smf user %s" % username) + logger.debug(f"Deleting smf user {username}") cursor = connections['smf'].cursor() if cls.check_user(username): cursor.execute(cls.SQL_DEL_USER, [username]) - logger.info("Deleted smf user %s" % username) + logger.info(f"Deleted smf user {username}") return True - logger.error("Unable to delete smf user %s - user not found on smf." % username) + logger.error(f"Unable to delete smf user {username} - user not found on smf.") return False @classmethod @@ -218,8 +269,8 @@ class SmfManager: cursor = connections['smf'].cursor() cursor.execute(cls.SQL_ADD_USER_GROUP, [groupid, userid]) logger.info(f"Added smf user id {userid} to group id {groupid}") - except: - logger.exception(f"Unable to add smf user id {userid} to group id {groupid}") + except Exception as e: + logger.exception(f"Unable to add smf user id {userid} to group id {groupid} ({e})") pass @classmethod @@ -229,13 +280,13 @@ class SmfManager: cursor = connections['smf'].cursor() cursor.execute(cls.SQL_REMOVE_USER_GROUP, [groupid, userid]) logger.info(f"Removed smf user id {userid} from group id {groupid}") - except: - logger.exception(f"Unable to remove smf user id {userid} from group id {groupid}") + except Exception as e: + logger.exception(f"Unable to remove smf user id {userid} from group id {groupid} ({e})") pass @classmethod def disable_user(cls, username): - logger.debug("Disabling smf user %s" % username) + logger.debug(f"Disabling smf user {username}") cursor = connections['smf'].cursor() password = cls.generate_random_pass() @@ -245,15 +296,15 @@ class SmfManager: cursor.execute(cls.SQL_DIS_USER, [revoke_email, pwhash, username]) cls.get_user_id(username) cls.update_groups(username, []) - logger.info("Disabled smf user %s" % username) + logger.info(f"Disabled smf user {username}") return True except TypeError: - logger.exception("TypeError occured while disabling user %s - failed to disable." % username) + logger.exception(f"TypeError occured while disabling user {username} - failed to disable.") return False @classmethod def update_user_password(cls, username, characterid, password=None): - logger.debug("Updating smf user %s password" % username) + logger.debug(f"Updating smf user {username} password") cursor = connections['smf'].cursor() if not password: password = cls.generate_random_pass() @@ -261,10 +312,12 @@ class SmfManager: username_clean = cls.santatize_username(username) pwhash = cls.gen_hash(username_clean, password) logger.debug( - f"Proceeding to update smf user {username} password with pwhash starting with {pwhash[0:5]}") + f"Proceeding to update smf user {username} " + f"password with pwhash starting with {pwhash[0:5]}" + ) cursor.execute(cls.SQL_UPDATE_USER_PASSWORD, [pwhash, username]) cls.add_avatar(username, characterid) - logger.info("Updated smf user %s password." % username) + logger.info(f"Updated smf user {username} password.") return password - logger.error("Unable to update smf user %s password - user not found on smf." % username) + logger.error(f"Unable to update smf user {username} password - user not found on smf.") return ""