mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-11 05:20:16 +02:00
* Port to Django 1.10 Initial migrations for current states of all models. Requires faking to retain data. Removed all references to render_to_response, replacing with render shortcut. Same for HttpResponseRedirect to render shortcut. Corrected notification signal import to wait for app registry to finish loading. * Correct typos from render conversion * Modify models to suppress Django field warnings * Script for automatic database conversion - fakes initial migrations to preserve data Include LOGIN_URL setting * Correct context processor import typo * Removed pathfinder support. Current pathfinder versions require SSO, not APIs added to database. Conditionally load additional database definitions only if services are enabled. Prevents errors when running auth without creating all possible databases. * Condense context processors * Include Django 1.10 installation in migrate script Remove syncdb/evolve, replace with migrate for update script * Replaced member/blue perms with user state system Removed sigtracker Initial migrations for default perms and groups Removed perm bootstrapping on first run * Clean up services list * Remove fleet fittings page * Provide action feedback via django messaging Display unread notification count Correct left navbar alignment * Stop storing service passwords. Provide them one time upon activation or reset. Closes #177 * Add group sync buttons to admin site Allow searcing of AuthServicesInfo models Display user main character * Correct button CSS to remove underlines on hover * Added bulk actions to notifications Altered notification default ordering * Centralize API key validation. Remove unused error count on API key model. Restructure API key refresh task to queue all keys per user and await completion. Closes #350 * Example configuration files for supervisor. Copy to /etc/supervisor/conf.d and restart to take effect. Closes #521 Closes #266 * Pre-save receiver for member/blue state switching Removed is_blue field Added link to admin site * Remove all hardcoded URLs from views and templates Correct missing render arguments Closes #540 * Correct celeryd process directory * Migration to automatically set user states. Runs instead of waiting for next API refresh cycle. Should make the transition much easier. * Verify service accounts accessible to member state * Restructure project to remove unnecessary apps. (celerytask, util, portal, registraion apps) Added workarounds for python 3 compatibility. * Correct python2 compatibility * Check services against state being changed to * Python3 compatibility fixes * Relocate x2bool py3 fix * SSO integration for logging in to existing accounts. * Add missing url names for fleetup reverse * Sanitize groupnames before syncing. * Correct trailing slash preventing url resolution * Alter group name sanitization to allow periods and hyphens * Correct state check on pre_save model for corp/alliance group assignment * Remove sigtracker table from old dbs to allow user deletion * Include missing celery configuration * Teamspeak error handling * Prevent celery worker deadlock on async group result wait * Correct active navbar links for translated urls. Correct corp status url resolution for some links. Remove DiscordAuthToken model.
201 lines
7.5 KiB
Python
Executable File
201 lines
7.5 KiB
Python
Executable File
from __future__ import unicode_literals
|
|
from django.utils import six
|
|
import re
|
|
import os
|
|
try:
|
|
from urlparse import urlparse
|
|
except ImportError:
|
|
# python 3
|
|
from urllib.parse import urlparse
|
|
|
|
import sleekxmpp
|
|
from django.conf import settings
|
|
import threading
|
|
from ofrestapi.users import Users as ofUsers
|
|
from ofrestapi import exception
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class OpenfireManager:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@staticmethod
|
|
def send_broadcast_threaded(group_name, broadcast_message):
|
|
logger.debug("Starting broadcast to %s with message %s" % (group_name, broadcast_message))
|
|
broadcast_thread = XmppThread(1, "XMPP Broadcast Thread", 1, group_name, broadcast_message)
|
|
broadcast_thread.start()
|
|
|
|
@staticmethod
|
|
def __add_address_to_username(username):
|
|
address = urlparse(settings.OPENFIRE_ADDRESS).netloc.split(":")[0]
|
|
completed_username = username + "@" + address
|
|
return completed_username
|
|
|
|
@staticmethod
|
|
def __santatize_username(username):
|
|
sanatized = username.replace(" ", "_")
|
|
return sanatized.lower()
|
|
|
|
@staticmethod
|
|
def __generate_random_pass():
|
|
return os.urandom(8).encode('hex')
|
|
|
|
@staticmethod
|
|
def _sanitize_groupname(name):
|
|
name = name.strip(' _')
|
|
return re.sub('[^\w.-]', '', name)
|
|
|
|
@staticmethod
|
|
def add_user(username):
|
|
logger.debug("Adding username %s to openfire." % username)
|
|
try:
|
|
sanatized_username = OpenfireManager.__santatize_username(username)
|
|
password = OpenfireManager.__generate_random_pass()
|
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
|
api.add_user(sanatized_username, password)
|
|
logger.info("Added openfire user %s" % username)
|
|
except exception.UserAlreadyExistsException:
|
|
# User exist
|
|
logger.error("Attempting to add a user %s to openfire which already exists on server." % username)
|
|
return "", ""
|
|
|
|
return sanatized_username, password
|
|
|
|
@staticmethod
|
|
def delete_user(username):
|
|
logger.debug("Deleting user %s from openfire." % username)
|
|
try:
|
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
|
api.delete_user(username)
|
|
logger.info("Deleted user %s from openfire." % username)
|
|
return True
|
|
except exception.UserNotFoundException:
|
|
logger.error("Attempting to delete a user %s from openfire which was not found on server." % username)
|
|
return False
|
|
|
|
@staticmethod
|
|
def lock_user(username):
|
|
logger.debug("Locking openfire user %s" % username)
|
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
|
api.lock_user(username)
|
|
logger.info("Locked openfire user %s" % username)
|
|
|
|
@staticmethod
|
|
def unlock_user(username):
|
|
logger.debug("Unlocking openfire user %s" % username)
|
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
|
api.unlock_user(username)
|
|
logger.info("Unlocked openfire user %s" % username)
|
|
|
|
@staticmethod
|
|
def update_user_pass(username, password=None):
|
|
logger.debug("Updating openfire user %s password." % username)
|
|
try:
|
|
if not password:
|
|
password = OpenfireManager.__generate_random_pass()
|
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
|
api.update_user(username, password=password)
|
|
logger.info("Updated openfire user %s password." % username)
|
|
return password
|
|
except exception.UserNotFoundException:
|
|
logger.error("Unable to update openfire user %s password - user not found on server." % username)
|
|
return ""
|
|
|
|
@staticmethod
|
|
def update_user_groups(username, groups):
|
|
logger.debug("Updating openfire user %s groups %s" % (username, groups))
|
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
|
response = api.get_user_groups(username)
|
|
remote_groups = []
|
|
if response:
|
|
remote_groups = response['groupname']
|
|
if isinstance(remote_groups, six.string_types):
|
|
remote_groups = [remote_groups]
|
|
logger.debug("Openfire user %s has groups %s" % (username, remote_groups))
|
|
add_groups = []
|
|
del_groups = []
|
|
for g in groups:
|
|
g = OpenfireManager._sanitize_groupname(g)
|
|
if g not in remote_groups:
|
|
add_groups.append(g)
|
|
for g in remote_groups:
|
|
g = OpenfireManager._sanitize_groupname(g)
|
|
if g not in groups:
|
|
del_groups.append(g)
|
|
logger.info(
|
|
"Updating openfire groups for user %s - adding %s, removing %s" % (username, add_groups, del_groups))
|
|
if add_groups:
|
|
api.add_user_groups(username, add_groups)
|
|
if del_groups:
|
|
api.delete_user_groups(username, del_groups)
|
|
|
|
@staticmethod
|
|
def delete_user_groups(username, groups):
|
|
logger.debug("Deleting openfire groups %s from user %s" % (groups, username))
|
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
|
api.delete_user_groups(username, groups)
|
|
logger.info("Deleted groups %s from openfire user %s" % (groups, username))
|
|
|
|
@staticmethod
|
|
def send_broadcast_message(group_name, broadcast_message):
|
|
logger.debug("Sending jabber ping to group %s with message %s" % (group_name, broadcast_message))
|
|
to_address = group_name + '@' + settings.BROADCAST_SERVICE_NAME + '.' + settings.JABBER_URL
|
|
xmpp = PingBot(settings.BROADCAST_USER, settings.BROADCAST_USER_PASSWORD, to_address, broadcast_message)
|
|
xmpp.register_plugin('xep_0030') # Service Discovery
|
|
xmpp.register_plugin('xep_0199') # XMPP Ping
|
|
if xmpp.connect():
|
|
xmpp.process(block=True)
|
|
logger.info("Sent jabber ping to group %s" % group_name)
|
|
else:
|
|
raise ValueError("Unable to connect to jabber server.")
|
|
|
|
|
|
class PingBot(sleekxmpp.ClientXMPP):
|
|
"""
|
|
A copy-paste of the example client bot from
|
|
http://sleekxmpp.com/getting_started/sendlogout.html
|
|
"""
|
|
def __init__(self, jid, password, recipient, message):
|
|
sleekxmpp.ClientXMPP.__init__(self, jid, password)
|
|
|
|
# The message we wish to send, and the JID that
|
|
# will receive it.
|
|
self.recipient = recipient
|
|
self.msg = message
|
|
|
|
# The session_start event will be triggered when
|
|
# the bot establishes its connection with the server
|
|
# and the XML streams are ready for use. We want to
|
|
# listen for this event so that we we can initialize
|
|
# our roster.
|
|
self.add_event_handler("session_start", self.start)
|
|
|
|
def start(self, event):
|
|
self.send_presence()
|
|
self.get_roster()
|
|
|
|
self.send_message(mto=self.recipient,
|
|
mbody=self.msg,
|
|
mtype='chat')
|
|
|
|
# Using wait=True ensures that the send queue will be
|
|
# emptied before ending the session.
|
|
self.disconnect(wait=True)
|
|
|
|
|
|
class XmppThread(threading.Thread):
|
|
def __init__(self, thread_id, name, counter, group, message, ):
|
|
threading.Thread.__init__(self)
|
|
self.threadID = thread_id
|
|
self.name = name
|
|
self.counter = counter
|
|
self.group = group
|
|
self.message = message
|
|
|
|
def run(self):
|
|
OpenfireManager.send_broadcast_message(self.group, self.message)
|