Merge branch '1088-qol-improve-name-handling-for-smf' into 'master'

Displayed names for SMF

Closes #1088

See merge request allianceauth/allianceauth!1459
This commit is contained in:
Ariel Rin 2022-09-11 13:53:25 +00:00
commit 273bda173e
5 changed files with 178 additions and 29 deletions

View File

@ -38,6 +38,12 @@ class SmfService(ServicesHook):
if SmfTasks.has_account(user):
SmfTasks.update_groups.delay(user.pk)
def sync_nickname(self, user):
logger.debug(f"Updating {self.name} displayed name for {user}")
if SmfTasks.has_account(user):
SmfTasks.update_display_name.apply_async(args=[user.pk], countdown=5) # cooldown on this task to ensure DB clean when syncing
def update_all_groups(self):
logger.debug('Update all %s groups called' % self.name)
SmfTasks.update_all_groups.delay()

View File

@ -5,11 +5,14 @@ from datetime import datetime
import hashlib
import logging
import re
from typing import Tuple
from packaging import version
from django.db import connections
from django.conf import settings
from django.contrib.auth.models import User
from allianceauth.eveonline.models import EveCharacter
logger = logging.getLogger(__name__)
@ -37,6 +40,10 @@ class SmfManager:
SQL_DEL_USER = r"DELETE FROM %smembers where member_name = %%s" % TABLE_PREFIX
SQL_UPD_USER = r"UPDATE %smembers SET email_address = %%s, passwd = %%s, real_name = %%s WHERE member_name = %%s" % TABLE_PREFIX
SQL_UPD_DISPLAY_NAME = r"UPDATE %smembers SET real_name = %%s WHERE member_name = %%s" % TABLE_PREFIX
SQL_DIS_USER = r"UPDATE %smembers SET email_address = %%s, passwd = %%s WHERE member_name = %%s" % TABLE_PREFIX
SQL_USER_ID_FROM_USERNAME = r"SELECT id_member from %smembers WHERE member_name = %%s" % TABLE_PREFIX
@ -174,50 +181,75 @@ class SmfManager:
return out
@classmethod
def add_user(cls, username, email_address, groups, characterid):
def add_user(cls, username, email_address, groups, main_character: EveCharacter) -> Tuple:
"""
Add a user to SMF
:param username:
:param email_address:
:param groups:
:param main_character:
:return:
"""
main_character_id = main_character.character_id
main_character_name = main_character.character_name
logger.debug(
f"Adding smf user with member_name {username}, "
f"email_address {email_address}, "
f"characterid {characterid}"
f"Adding smf user with member_name: {username}, "
f"email_address: {email_address}, "
f"characterid: {main_character_id}, "
f"main character: {main_character_name}"
)
cursor = connections['smf'].cursor()
username_clean = cls.santatize_username(username)
passwd = cls.generate_random_pass()
pwhash = cls.gen_hash(username_clean, passwd)
logger.debug(f"Proceeding to add smf user {username} and pwhash starting with {pwhash[0:5]}")
register_date = cls.get_current_utc_date()
logger.debug(f"Proceeding to add smf user {username} and pwhash starting with {pwhash[0:5]}")
# check if the username was simply revoked
if cls.check_user(username) is True:
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)
logger.warning(
f"Unable to add smf user with username {username} - "
f"already exists. Updating user instead."
)
cls.__update_user_info(
username_clean, email_address, pwhash, main_character_name
)
else:
try:
smf_version = cls._get_current_smf_version()
sql_add_user_arguments = [
username_clean,
pwhash,
email_address,
register_date,
main_character_name,
]
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]
)
cursor.execute(cls.SQL_ADD_USER_SMF_20, sql_add_user_arguments)
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)
cursor.execute(cls.SQL_ADD_USER_SMF_21, sql_add_user_arguments)
cls.add_avatar(username_clean, main_character_id)
logger.info(f"Added smf member_name {username_clean}")
cls.update_groups(username_clean, groups)
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):
def __update_user_info(cls, username, email_address, passwd, main_character_name):
logger.debug(
f"Updating smf user {username} info: "
f"username {email_address} "
@ -225,7 +257,9 @@ class SmfManager:
)
cursor = connections['smf'].cursor()
try:
cursor.execute(cls.SQL_DIS_USER, [email_address, passwd, username])
cursor.execute(
cls.SQL_UPD_USER, [email_address, passwd, main_character_name, username]
)
logger.info(f"Updated smf user {username} info")
except Exception as e:
logger.exception(f"Unable to update smf user {username} info. ({e})")
@ -243,6 +277,27 @@ class SmfManager:
logger.error(f"Unable to delete smf user {username} - user not found on smf.")
return False
@classmethod
def update_display_name(cls, user: User):
logger.debug(f"Updating SMF displayed name for user {user}")
cursor = connections['smf'].cursor()
smf_username = user.smf.username
try:
display_name = user.profile.main_character.character_name
except Exception as exc:
logger.exception(
f"Unable to find a main character name for {user}, skipping... ({exc})"
)
display_name = smf_username
if cls.check_user(smf_username):
cursor.execute(cls.SQL_UPD_DISPLAY_NAME, [display_name, smf_username])
logger.info(f"Updated displayed name for smf user {smf_username}")
return True
logger.error(f"Unable to update smf user {smf_username} - user not found on smf.")
return False
@classmethod
def update_groups(cls, username, groups):
userid = cls.get_user_id(username)

View File

@ -0,0 +1,29 @@
from django.db import migrations
from ..manager import SmfManager
def on_migrate(apps, schema_editor):
SmfUser = apps.get_model("smf", "SmfUser")
db_alias = schema_editor.connection.alias
all_smf_users = SmfUser.objects.using(db_alias).all()
for smf_user in all_smf_users:
try:
auth_user = smf_user.user
except:
pass
else:
SmfManager.update_display_name(auth_user)
def on_migrate_zero(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('smf', '0002_service_permissions'),
]
operations = [
migrations.RunPython(on_migrate, on_migrate_zero),
]

View File

@ -57,6 +57,40 @@ class SmfTasks:
else:
logger.debug("User does not have an smf account")
@staticmethod
@shared_task(bind=True, name="smf.update_display_name", base=QueueOnce)
def update_display_name(self, pk):
user = User.objects.get(pk=pk)
logger.debug(f"Updating SMF displayed name user {user}")
if SmfTasks.has_account(user):
try:
if not SmfManager.update_display_name(user):
raise Exception("SMF Displayed Name Sync failed")
logger.debug(f"Updated user {user} SMF displayed name.")
return True
except SmfUser.DoesNotExist:
logger.info(
f"SMF displayed name sync failed for {user}, "
"user does not have a SMF account"
)
except:
logger.exception(
f"SMF displayed name sync failed for {user}, retrying in 10 mins"
)
raise self.retry(countdown=60 * 10)
else:
logger.debug(f"User {user} does not have a SMF account, skipping")
return False
@staticmethod
@shared_task(name="smf.update_all_display_names")
def update_all_display_names():
logger.debug("Updating ALL SMF display names")
for smf_user in SmfUser.objects.exclude(username__exact=''):
SmfTasks.update_display_name.delay(smf_user)
@staticmethod
@shared_task(name="smf.update_all_groups")
def update_all_groups():

View File

@ -19,26 +19,51 @@ ACCESS_PERM = 'smf.access_smf'
@login_required
@permission_required(ACCESS_PERM)
def activate_smf(request):
logger.debug("activate_smf called by user %s" % request.user)
logger.debug(f"activate_smf called by user {request.user}")
# Valid now we get the main characters
character = request.user.profile.main_character
logger.debug(f"Adding smf user for user {request.user} with main character {character}")
result = SmfManager.add_user(SmfTasks.get_username(request.user), request.user.email, ['Member'], character.character_id)
main_character = request.user.profile.main_character
logger.debug(
f"Adding smf user for user {request.user} with main character {main_character}"
)
result = SmfManager.add_user(
SmfTasks.get_username(request.user),
request.user.email,
['Member'],
main_character,
)
# if empty we failed
if result[0] != "":
SmfUser.objects.update_or_create(user=request.user, defaults={'username': result[0]})
logger.debug("Updated authserviceinfo for user %s with smf credentials. Updating groups." % request.user)
SmfUser.objects.update_or_create(
user=request.user, defaults={'username': result[0]}
)
logger.debug(
f"Updated authserviceinfo for user {request.user} "
f"with smf credentials. Updating groups."
)
SmfTasks.update_groups.delay(request.user.pk)
logger.info("Successfully activated smf for user %s" % request.user)
logger.info(f"Successfully activated smf for user {request.user}")
messages.success(request, _('Activated SMF account.'))
credentials = {
'username': result[0],
'password': result[1],
}
return render(request, 'services/service_credentials.html', context={'credentials': credentials, 'service': 'SMF'})
else:
logger.error("Unsuccessful attempt to activate smf for user %s" % request.user)
messages.error(request, _('An error occurred while processing your SMF account.'))
return render(
request,
'services/service_credentials.html',
context={'credentials': credentials, 'service': 'SMF'},
)
logger.error(f"Unsuccessful attempt to activate smf for user {request.user}")
messages.error(request, _('An error occurred while processing your SMF account.'))
return redirect("services:services")