The Great Services Refactor (#594)

* Hooks registration, discovery and retrieval module

Will discover @hooks.register decorated functions inside
the auth_hooks module in any installed django app.

* Class to register modular service apps

* Register service modules URLs

* Example service module

* Refactor services into modules

Each service type has been split out into its own django app/module. A
hook mechanism is provided to register a subclass of the ServiceHook
class. The modules then overload functions defined in ServiceHook as
required to provide interoperability with alliance auth. Service modules
provide their own urls and views for user registration and account
management and a partial template to display on the services page. Where
possible, new modules should provide their own models for local data
storage.

* Added menu items hooks and template tags

* Added menu item hook for broadcasts

* Added str method to ServicesHook

* Added exception handling to hook iterators

* Refactor mumble migration and table name

Upgrading will require `migrate mumble --fake-initial` to be run first
and then `migrate mumble` to rename the table.

* Refactor teamspeak3 migration and rename table

Upgrading will require `migrate teamspeak3 --fake-initial`

* Added module models and migrations for refactoring AuthServicesInfo

* Migrate AuthServiceInfo fields to service modules models

* Added helper for getting a users main character

* Added new style celery instance

* Changed Discord from AuthServicesInfo to DiscordUser model

* Switch celery tasks to staticmethods

* Changed Discourse from AuthServicesInfo to DiscourseUser model

* Changed IPBoard from AuthServicesInfo to IpboardUser model

* Changed Ips4 from AuthServicesInfo to Ips4User model

Also added disable service task.

This service still needs some love though. Was always missing a
deactivate services hook (before refactoring) for reasons I'm unsure of
so I'm reluctant to add it without knowing why.

* Changed Market from AuthServicesInfo to MarketUser model

* Changed Mumble from AuthServicesInfo to MumbleUser model

Switched user foreign key to one to one relationship.
Removed implicit password change on user exists.
Combined regular and blue user creation.

* Changed Openfire from AuthServicesInfo to OpenfireUser model

* Changed SMF from AuthServicesInfo to SmfUser model

Added disable task

* Changed Phpbb3 from AuthServicesInfo to Phpbb3User model

* Changed XenForo from AuthServicesInfo to XenforoUser model

* Changed Teamspeak3 from AuthServicesInfo to Teamspeak3User model

* Remove obsolete manager functions

* Standardise URL format

This will break some callback URLs
Discord changes from /discord_callback/ to /discord/callback/

* Removed unnecessary imports

* Mirror upstream decorator change

* Setup for unit testing

* Unit tests for discord service

* Added add main character helper

* Added Discourse unit tests

* Added Ipboard unit tests

* Added Ips4 unit tests

* Fix naming of market manager, switch to use class methods

* Remove unused hook functions

* Added market service unit tests

* Added corp ticker to add main character helper

* Added mumble unit tests

* Fix url name and remove namespace

* Fix missing return and add missing URL

* Added openfire unit tests

* Added missing return

* Added phpbb3 unit tests

* Fix SmfManager naming inconsistency and switch to classmethods

* Added smf unit tests

* Remove unused functions, Added missing return

* Added xenforo unit tests

* Added missing return

* Fixed reference to old model

* Fixed error preventing groups from syncing on reset request

* Added teamspeak3 unit tests

* Added nose as test runner and some test settings

* Added package requirements for running tests

* Added unit tests for services signals and tasks

* Remove unused tests file

* Fix teamspeak3 service signals

* Added unit tests for teamspeak3 signals

Changed other unit tests setUp to inert signals

* Fix password gen and hashing python3 compatibility

Fixes #630

Adds unit tests to check the password functions run on both platforms.

* Fix unit test to not rely on checking url params

* Add Travis CI settings file

* Remove default blank values from services models

* Added dynamic user model admin actions for syncing service groups

* Remove unused search fields

* Add hook function for syncing nicknames

* Added discord hook for sync nickname

* Added user admin model menu actions for sync nickname hook

* Remove obsolete code

* Rename celery config app to avoid package name clash

* Added new style celerybeat schedule configuration

periodic_task decorator is depreciated

* Added string representations

* Added admin pages for services user models

* Removed legacy code

* Move link discord button to correct template

* Remove blank default fields from example model

* Disallow empty django setting

* Fix typos

* Added coverage configuration file

* Add coverage and coveralls to travis config

Should probably use nose's built in coverage, but this works for now.

* Replace AuthServicesInfo get_or_create instances with get

Reflects upstream changes to AuthServicesInfo behaviour.

* Update mumble user table name

* Split out mumble authenticator requirements

zeroc-ice seems to cause long build times on travis-ci and isn't
required for the core projects functionality or testing.
This commit is contained in:
Basraah
2017-01-25 12:50:16 +10:00
committed by GitHub
parent 5738b015c3
commit 1066e6ac98
195 changed files with 8260 additions and 2699 deletions

View File

@@ -1,201 +0,0 @@
from __future__ import unicode_literals
import requests
import json
import re
from django.conf import settings
from services.models import GroupCache
from requests_oauthlib import OAuth2Session
import logging
import datetime
from django.utils import timezone
logger = logging.getLogger(__name__)
DISCORD_URL = "https://discordapp.com/api"
EVE_IMAGE_SERVER = "https://image.eveonline.com"
AUTH_URL = "https://discordapp.com/api/oauth2/authorize"
TOKEN_URL = "https://discordapp.com/api/oauth2/token"
# needs administrator, since Discord can't get their permissions system to work
# was kick members, manage roles, manage nicknames
#BOT_PERMISSIONS = 0x00000002 + 0x10000000 + 0x08000000
BOT_PERMISSIONS = 0x00000008
# get user ID, accept invite
SCOPES = [
'identify',
'guilds.join',
]
GROUP_CACHE_MAX_AGE = datetime.timedelta(minutes=30)
class DiscordOAuthManager:
def __init__(self):
pass
@staticmethod
def _sanitize_groupname(name):
name = name.strip(' _')
return re.sub('[^\w.-]', '', name)
@staticmethod
def generate_bot_add_url():
return AUTH_URL + '?client_id=' + settings.DISCORD_APP_ID + '&scope=bot&permissions=' + str(BOT_PERMISSIONS)
@staticmethod
def generate_oauth_redirect_url():
oauth = OAuth2Session(settings.DISCORD_APP_ID, redirect_uri=settings.DISCORD_CALLBACK_URL, scope=SCOPES)
url, state = oauth.authorization_url(AUTH_URL)
return url
@staticmethod
def _process_callback_code(code):
oauth = OAuth2Session(settings.DISCORD_APP_ID, redirect_uri=settings.DISCORD_CALLBACK_URL)
token = oauth.fetch_token(TOKEN_URL, client_secret=settings.DISCORD_APP_SECRET, code=code)
return token
@staticmethod
def add_user(code):
try:
token = DiscordOAuthManager._process_callback_code(code)['access_token']
logger.debug("Received token from OAuth")
custom_headers = {'accept': 'application/json', 'authorization': 'Bearer ' + token}
path = DISCORD_URL + "/invites/" + str(settings.DISCORD_INVITE_CODE)
r = requests.post(path, headers=custom_headers)
logger.debug("Got status code %s after accepting Discord invite" % r.status_code)
r.raise_for_status()
path = DISCORD_URL + "/users/@me"
r = requests.get(path, headers=custom_headers)
logger.debug("Got status code %s after retrieving Discord profile" % r.status_code)
r.raise_for_status()
user_id = r.json()['id']
logger.info("Added Discord user ID %s to server." % user_id)
return user_id
except:
logger.exception("Failed to add Discord user")
return None
@staticmethod
def update_nickname(user_id, nickname):
try:
custom_headers = {'content-type': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
data = {'nick': nickname, }
path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/members/" + str(user_id)
r = requests.patch(path, headers=custom_headers, json=data)
logger.debug("Got status code %s after setting nickname for Discord user ID %s (%s)" % (
r.status_code, user_id, nickname))
if r.status_code == 404:
logger.warn("Discord user ID %s could not be found in server." % user_id)
return True
r.raise_for_status()
return True
except:
logger.exception("Failed to set nickname for Discord user ID %s (%s)" % (user_id, nickname))
return False
@staticmethod
def delete_user(user_id):
try:
custom_headers = {'accept': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/members/" + str(user_id)
r = requests.delete(path, headers=custom_headers)
logger.debug("Got status code %s after removing Discord user ID %s" % (r.status_code, user_id))
if r.status_code == 404:
logger.warn("Discord user ID %s already left the server." % user_id)
return True
r.raise_for_status()
return True
except:
logger.exception("Failed to remove Discord user ID %s" % user_id)
return False
@staticmethod
def __get_groups():
custom_headers = {'accept': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/roles"
r = requests.get(path, headers=custom_headers)
logger.debug("Got status code %s after retrieving Discord roles" % r.status_code)
r.raise_for_status()
return r.json()
@staticmethod
def __update_group_cache():
GroupCache.objects.filter(service="discord").delete()
cache = GroupCache.objects.create(service="discord")
cache.groups = json.dumps(DiscordOAuthManager.__get_groups())
cache.save()
return cache
@staticmethod
def __get_group_cache():
if not GroupCache.objects.filter(service="discord").exists():
DiscordOAuthManager.__update_group_cache()
cache = GroupCache.objects.get(service="discord")
age = timezone.now() - cache.created
if age > GROUP_CACHE_MAX_AGE:
logger.debug("Group cache has expired. Triggering update.")
cache = DiscordOAuthManager.__update_group_cache()
return json.loads(cache.groups)
@staticmethod
def __group_name_to_id(name):
cache = DiscordOAuthManager.__get_group_cache()
for g in cache:
if g['name'] == name:
return g['id']
logger.debug("Group %s not found on Discord. Creating" % name)
DiscordOAuthManager.__create_group(name)
return DiscordOAuthManager.__group_name_to_id(name)
@staticmethod
def __group_id_to_name(id):
cache = DiscordOAuthManager.__get_group_cache()
for g in cache:
if g['id'] == id:
return g['name']
raise KeyError("Group ID %s not found on Discord" % id)
@staticmethod
def __generate_role():
custom_headers = {'accept': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/roles"
r = requests.post(path, headers=custom_headers)
logger.debug("Received status code %s after generating new role." % r.status_code)
r.raise_for_status()
return r.json()
@staticmethod
def __edit_role(role_id, name, color=0, hoist=True, permissions=36785152):
custom_headers = {'content-type': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
data = {
'color': color,
'hoist': hoist,
'name': name,
'permissions': permissions,
}
path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/roles/" + str(role_id)
r = requests.patch(path, headers=custom_headers, data=json.dumps(data))
logger.debug("Received status code %s after editing role id %s" % (r.status_code, role_id))
r.raise_for_status()
return r.json()
@staticmethod
def __create_group(name):
role = DiscordOAuthManager.__generate_role()
DiscordOAuthManager.__edit_role(role['id'], name)
DiscordOAuthManager.__update_group_cache()
@staticmethod
def update_groups(user_id, groups):
custom_headers = {'content-type': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
group_ids = [DiscordOAuthManager.__group_name_to_id(DiscordOAuthManager._sanitize_groupname(g)) for g in groups]
path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/members/" + str(user_id)
data = {'roles': group_ids}
r = requests.patch(path, headers=custom_headers, json=data)
logger.debug("Received status code %s after setting user roles" % r.status_code)
r.raise_for_status()

View File

@@ -1,378 +0,0 @@
from __future__ import unicode_literals
import logging
import requests
import os
import datetime
import json
import re
from django.conf import settings
from django.utils import timezone
from services.models import GroupCache
logger = logging.getLogger(__name__)
class DiscourseError(Exception):
def __init__(self, endpoint, errors):
self.endpoint = endpoint
self.errors = errors
def __str__(self):
return "API execution failed.\nErrors: %s\nEndpoint: %s" % (self.errors, self.endpoint)
# not exhaustive, only the ones we need
ENDPOINTS = {
'groups': {
'list': {
'path': "/admin/groups.json",
'method': requests.get,
'args': {
'required': [],
'optional': [],
},
},
'create': {
'path': "/admin/groups",
'method': requests.post,
'args': {
'required': ['name'],
'optional': ['visible'],
}
},
'add_user': {
'path': "/admin/groups/%s/members.json",
'method': requests.put,
'args': {
'required': ['usernames'],
'optional': [],
},
},
'remove_user': {
'path': "/admin/groups/%s/members.json",
'method': requests.delete,
'args': {
'required': ['username'],
'optional': [],
},
},
'delete': {
'path': "/admin/groups/%s.json",
'method': requests.delete,
'args': {
'required': [],
'optional': [],
},
},
},
'users': {
'create': {
'path': "/users",
'method': requests.post,
'args': {
'required': ['name', 'email', 'password', 'username'],
'optional': ['active'],
},
},
'update': {
'path': "/users/%s.json",
'method': requests.put,
'args': {
'required': ['params'],
'optional': [],
}
},
'get': {
'path': "/users/%s.json",
'method': requests.get,
'args': {
'required': [],
'optional': [],
},
},
'activate': {
'path': "/admin/users/%s/activate",
'method': requests.put,
'args': {
'required': [],
'optional': [],
},
},
'set_email': {
'path': "/users/%s/preferences/email",
'method': requests.put,
'args': {
'required': ['email'],
'optional': [],
},
},
'suspend': {
'path': "/admin/users/%s/suspend",
'method': requests.put,
'args': {
'required': ['duration', 'reason'],
'optional': [],
},
},
'unsuspend': {
'path': "/admin/users/%s/unsuspend",
'method': requests.put,
'args': {
'required': [],
'optional': [],
},
},
'logout': {
'path': "/admin/users/%s/log_out",
'method': requests.post,
'args': {
'required': [],
'optional': [],
},
},
'external': {
'path': "/users/by-external/%s.json",
'method': requests.get,
'args': {
'required': [],
'optional': [],
},
},
},
}
class DiscourseManager:
def __init__(self):
pass
GROUP_CACHE_MAX_AGE = datetime.timedelta(minutes=30)
REVOKED_EMAIL = 'revoked@' + settings.DOMAIN
SUSPEND_DAYS = 99999
SUSPEND_REASON = "Disabled by auth."
@staticmethod
def __exc(endpoint, *args, **kwargs):
params = {
'api_key': settings.DISCOURSE_API_KEY,
'api_username': settings.DISCOURSE_API_USERNAME,
}
silent = kwargs.pop('silent', False)
if args:
endpoint['parsed_url'] = endpoint['path'] % args
else:
endpoint['parsed_url'] = endpoint['path']
data = {}
for arg in endpoint['args']['required']:
data[arg] = kwargs[arg]
for arg in endpoint['args']['optional']:
if arg in kwargs:
data[arg] = kwargs[arg]
for arg in kwargs:
if arg not in endpoint['args']['required'] and arg not in endpoint['args']['optional'] and not silent:
logger.warn("Received unrecognized kwarg %s for endpoint %s" % (arg, endpoint))
r = endpoint['method'](settings.DISCOURSE_URL + endpoint['parsed_url'], params=params, json=data)
try:
if 'errors' in r.json() and not silent:
logger.error("Discourse execution failed.\nEndpoint: %s\nErrors: %s" % (endpoint, r.json()['errors']))
raise DiscourseError(endpoint, r.json()['errors'])
if 'success' in r.json():
if not r.json()['success'] and not silent:
raise DiscourseError(endpoint, None)
out = r.json()
except ValueError:
out = r.text
finally:
try:
r.raise_for_status()
except requests.exceptions.HTTPError as e:
raise DiscourseError(endpoint, e.response.status_code)
return out
@staticmethod
def __generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def __get_groups():
endpoint = ENDPOINTS['groups']['list']
data = DiscourseManager.__exc(endpoint)
return [g for g in data if not g['automatic']]
@staticmethod
def __update_group_cache():
GroupCache.objects.filter(service="discourse").delete()
cache = GroupCache.objects.create(service="discourse")
cache.groups = json.dumps(DiscourseManager.__get_groups())
cache.save()
return cache
@staticmethod
def __get_group_cache():
if not GroupCache.objects.filter(service="discourse").exists():
DiscourseManager.__update_group_cache()
cache = GroupCache.objects.get(service="discourse")
age = timezone.now() - cache.created
if age > DiscourseManager.GROUP_CACHE_MAX_AGE:
logger.debug("Group cache has expired. Triggering update.")
cache = DiscourseManager.__update_group_cache()
return json.loads(cache.groups)
@staticmethod
def __create_group(name):
endpoint = ENDPOINTS['groups']['create']
DiscourseManager.__exc(endpoint, name=name[:20], visible=True)
DiscourseManager.__update_group_cache()
@staticmethod
def __group_name_to_id(name):
cache = DiscourseManager.__get_group_cache()
for g in cache:
if g['name'] == name[0:20]:
return g['id']
logger.debug("Group %s not found on Discourse. Creating" % name)
DiscourseManager.__create_group(name)
return DiscourseManager.__group_name_to_id(name)
@staticmethod
def __group_id_to_name(id):
cache = DiscourseManager.__get_group_cache()
for g in cache:
if g['id'] == id:
return g['name']
raise KeyError("Group ID %s not found on Discourse" % id)
@staticmethod
def __add_user_to_group(id, username):
endpoint = ENDPOINTS['groups']['add_user']
DiscourseManager.__exc(endpoint, id, usernames=[username])
@staticmethod
def __remove_user_from_group(id, username):
endpoint = ENDPOINTS['groups']['remove_user']
DiscourseManager.__exc(endpoint, id, username=username)
@staticmethod
def __generate_group_dict(names):
group_dict = {}
for name in names:
group_dict[name] = DiscourseManager.__group_name_to_id(name)
return group_dict
@staticmethod
def __get_user_groups(username):
data = DiscourseManager.__get_user(username)
return [g['id'] for g in data['user']['groups'] if not g['automatic']]
@staticmethod
def __user_name_to_id(name, silent=False):
data = DiscourseManager.__get_user(name, silent=silent)
return data['user']['id']
@staticmethod
def __user_id_to_name(id):
raise NotImplementedError
@staticmethod
def __get_user(username, silent=False):
endpoint = ENDPOINTS['users']['get']
return DiscourseManager.__exc(endpoint, username, silent=silent)
@staticmethod
def __activate_user(username):
endpoint = ENDPOINTS['users']['activate']
id = DiscourseManager.__user_name_to_id(username)
DiscourseManager.__exc(endpoint, id)
@staticmethod
def __update_user(username, **kwargs):
endpoint = ENDPOINTS['users']['update']
id = DiscourseManager.__user_name_to_id(username)
DiscourseManager.__exc(endpoint, id, params=kwargs)
@staticmethod
def __create_user(username, email, password):
endpoint = ENDPOINTS['users']['create']
DiscourseManager.__exc(endpoint, name=username, username=username, email=email, password=password, active=True)
@staticmethod
def __check_if_user_exists(username):
try:
DiscourseManager.__user_name_to_id(username, silent=True)
return True
except:
return False
@staticmethod
def __suspend_user(username):
id = DiscourseManager.__user_name_to_id(username)
endpoint = ENDPOINTS['users']['suspend']
return DiscourseManager.__exc(endpoint, id, duration=DiscourseManager.SUSPEND_DAYS,
reason=DiscourseManager.SUSPEND_REASON)
@staticmethod
def __unsuspend(username):
id = DiscourseManager.__user_name_to_id(username)
endpoint = ENDPOINTS['users']['unsuspend']
return DiscourseManager.__exc(endpoint, id)
@staticmethod
def __set_email(username, email):
endpoint = ENDPOINTS['users']['set_email']
return DiscourseManager.__exc(endpoint, username, email=email)
@staticmethod
def __logout(id):
endpoint = ENDPOINTS['users']['logout']
return DiscourseManager.__exc(endpoint, id)
@staticmethod
def __get_user_by_external(id):
endpoint = ENDPOINTS['users']['external']
return DiscourseManager.__exc(endpoint, id)
@staticmethod
def __user_id_by_external_id(id):
data = DiscourseManager.__get_user_by_external(id)
return data['user']['id']
@staticmethod
def _sanitize_username(username):
sanitized = username.replace(" ", "_")
sanitized = sanitized.strip(' _')
sanitized = sanitized.replace("'", "")
return sanitized
@staticmethod
def _sanitize_groupname(name):
name = name.strip(' _')
name = re.sub('[^\w]', '', name)
if len(name) < 3:
name = name + "".join('_' for i in range(3-len(name)))
return name[:20]
@staticmethod
def update_groups(user):
groups = []
for g in user.groups.all():
groups.append(DiscourseManager._sanitize_groupname(str(g)[:20]))
logger.debug("Updating discourse user %s groups to %s" % (user, groups))
group_dict = DiscourseManager.__generate_group_dict(groups)
inv_group_dict = {v: k for k, v in group_dict.items()}
username = DiscourseManager.__get_user_by_external(user.pk)['user']['username']
user_groups = DiscourseManager.__get_user_groups(username)
add_groups = [group_dict[x] for x in group_dict if not group_dict[x] in user_groups]
rem_groups = [x for x in user_groups if not x in inv_group_dict]
if add_groups or rem_groups:
logger.info(
"Updating discourse user %s groups: adding %s, removing %s" % (username, add_groups, rem_groups))
for g in add_groups:
DiscourseManager.__add_user_to_group(g, username)
for g in rem_groups:
DiscourseManager.__remove_user_from_group(g, username)
@staticmethod
def disable_user(user):
logger.debug("Disabling user %s Discourse access." % user)
d_user = DiscourseManager.__get_user_by_external(user.pk)
DiscourseManager.__logout(d_user['user']['id'])
DiscourseManager.__suspend_user(d_user['user']['username'])
logger.info("Disabled user %s Discourse access." % user)
return True

View File

@@ -1,178 +0,0 @@
from __future__ import unicode_literals
from django.conf import settings
from datetime import datetime
import logging
import requests
import json
logger = logging.getLogger(__name__)
appkey = settings.FLEETUP_APP_KEY
userid = settings.FLEETUP_USER_ID
apiid = settings.FLEETUP_API_ID
groupid = settings.FLEETUP_GROUP_ID
class FleetUpManager:
def __init__(self):
pass
@staticmethod
def get_fleetup_members():
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/GroupCharacters/" + str(groupid) + ""
try:
jsondata = requests.get(url).content
fmembers = json.loads(jsondata.decode())
return {row["UserId"]: {"user_id": row["UserId"],
"char_name": row["EveCharName"],
"char_id": row["EveCharId"],
"corporation": row["Corporation"]} for row in fmembers["Data"]}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError, TypeError):
logger.debug("No fleetup members retrieved.")
return {}
@staticmethod
def get_fleetup_operations():
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/Operations/" + str(groupid) + ""
try:
jsondata = requests.get(url).content
foperations = json.loads(jsondata.decode())
return {row["StartString"]: {"subject": row["Subject"],
"start": (datetime.strptime(row["StartString"], "%Y-%m-%d %H:%M:%S")),
"end": (datetime.strptime(row["EndString"], "%Y-%m-%d %H:%M:%S")),
"operation_id": row["OperationId"],
"location": row["Location"],
"location_info": row["LocationInfo"],
"details": row["Details"],
"url": row["Url"],
"doctrine": row["Doctrines"],
"organizer": row["Organizer"]} for row in foperations["Data"]}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError):
logger.debug("No fleetup operations retrieved.")
return {}
@staticmethod
def get_fleetup_timers():
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/Timers/" + str(groupid) + ""
try:
jsondata = requests.get(url).content
ftimers = json.loads(jsondata.decode())
return {row["ExpiresString"]: {"solarsystem": row["SolarSystem"],
"planet": row["Planet"],
"moon": row["Moon"],
"owner": row["Owner"],
"type": row["Type"],
"timer_type": row["TimerType"],
"expires": (datetime.strptime(row["ExpiresString"], "%Y-%m-%d %H:%M:%S")),
"notes": row["Notes"]} for row in ftimers["Data"]}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError, TypeError):
logger.debug("No fleetup timers retrieved.")
return {}
@staticmethod
def get_fleetup_doctrines():
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/Doctrines/" + str(groupid) + ""
try:
jsondata = requests.get(url).content
fdoctrines = json.loads(jsondata.decode())
return {"fleetup_doctrines": fdoctrines["Data"]}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError):
logger.debug("No fleetup doctrines retrieved.")
return {"fleetup_doctrines": []}
@staticmethod
def get_fleetup_doctrine(doctrinenumber):
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/DoctrineFittings/%s" % doctrinenumber
try:
jsondata = requests.get(url).content
fdoctrine = json.loads(jsondata.decode())
return {"fitting_doctrine": fdoctrine}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError):
logger.warn("Fleetup doctrine number %s not found" % doctrinenumber)
return {"fitting_doctrine": {}}
@staticmethod
def get_fleetup_fittings():
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/Fittings/" + str(groupid) + ""
try:
jsondata = requests.get(url).content
ffittings = json.loads(jsondata.decode())
return {row["FittingId"]: {"fitting_id": row["FittingId"],
"name": row["Name"],
"icon_id": row["EveTypeId"],
"hull": row["HullType"],
"shiptype": row["ShipType"],
"estimated": row["EstPrice"],
"faction": row["Faction"],
"categories": row["Categories"],
"last_update": (
datetime.strptime(row["LastUpdatedString"], "%Y-%m-%d %H:%M:%S"))} for row in
ffittings["Data"]}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError, TypeError):
logger.debug("No fleetup fittings retrieved.")
return {}
@staticmethod
def get_fleetup_fitting(fittingnumber):
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/Fitting/%s" % fittingnumber
try:
jsondata = requests.get(url).content
ffitting = json.loads(jsondata.decode())
return {"fitting_data": ffitting["Data"]}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError):
logger.warn("Fleetup fitting number %s not found" % fittingnumber)
except KeyError:
logger.warn("Failed to retrieve fleetup fitting number %s" % fittingnumber)
return {"fitting_data": {}}
@staticmethod
def get_fleetup_doctrineid(fittingnumber):
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/Fitting/%s" % fittingnumber
try:
jsondata = requests.get(url).content
fdoctrineid = json.loads(jsondata.decode())
return fdoctrineid['Data']['Doctrines'][0]['DoctrineId']
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError):
logger.warn("Fleetup doctrine number not found for fitting number %s" % fittingnumber)
except (KeyError, IndexError):
logger.debug("Fleetup fitting number %s not in a doctrine." % fittingnumber)
return None
@staticmethod
def get_fleetup_fitting_eft(fittingnumber):
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(
apiid) + "/Fitting/%s/eft" % fittingnumber
try:
jsondata = requests.get(url).content
ffittingeft = json.loads(jsondata.decode())
return {"fitting_eft": ffittingeft["Data"]["FittingData"]}
except requests.exceptions.ConnectionError:
logger.warn("Can't connect to Fleet-Up API, is it offline?!")
except (ValueError, UnicodeDecodeError):
logger.warn("Fleetup fitting eft not found for fitting number %s" % fittingnumber)
return {"fitting_eft": {}}

View File

@@ -1,156 +0,0 @@
from __future__ import unicode_literals
import os
import re
from hashlib import md5
try:
from xmlrpclib import Server
except ImportError:
# python 3
from xmlrpc import server as Server
from django.conf import settings
import logging
logger = logging.getLogger(__name__)
class IPBoardManager:
def __init__(self):
pass
@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 exec_xmlrpc(func, **kwargs):
""" Send a XMLRPC request """
try:
server = Server(settings.IPBOARD_ENDPOINT, verbose=False)
params = {}
for i in kwargs:
params[i] = kwargs[i]
params['api_key'] = settings.IPBOARD_APIKEY
params['api_module'] = settings.IPBOARD_APIMODULE
return getattr(server, func)(params)
except:
return {}
@staticmethod
def add_user(username, email):
""" Add user to service """
sanatized = str(IPBoardManager.__santatize_username(username))
logger.debug("Adding user to IPBoard with username %s" % sanatized)
plain_password = IPBoardManager.__generate_random_pass()
password = md5(plain_password).hexdigest()
IPBoardManager.exec_xmlrpc('createUser', username=sanatized, email=str(email), display_name=sanatized,
md5_passwordHash=password)
logger.info("Added IPBoard user with username %s" % sanatized)
return sanatized, plain_password
@staticmethod
def delete_user(username):
""" Delete user """
IPBoardManager.exec_xmlrpc('deleteUser', username=username)
logger.info("Deleted IPBoard user with username %s" % username)
return username
@staticmethod
def disable_user(username):
""" Disable user """
IPBoardManager.exec_xmlrpc('disableUser', username=username)
logger.info("Disabled IPBoard user with username %s" % username)
return username
@staticmethod
def update_user(username, email, password):
""" Add user to service """
password = md5(password).hexdigest()
logger.debug("Updating IPBoard username %s with email %s and password hash starting with %s" % (
username, email, password[0:5]))
IPBoardManager.exec_xmlrpc('updateUser', username=username, email=email, md5_passwordHash=password)
logger.info("Updated IPBoard user with username %s" % username)
return username
@staticmethod
def get_all_groups():
groups = []
ret = IPBoardManager.exec_xmlrpc('getAllGroups')
for group in ret:
groups.append(group["g_title"])
logger.debug("Retrieved group list from IPBoard: %s" % groups)
return groups
@staticmethod
def get_user_groups(username):
groups = []
ret = IPBoardManager.exec_xmlrpc('getUserGroups', username=username)
if type(ret) is list:
for group in ret:
groups.append(group["g_title"])
logger.debug("Got user %s IPBoard groups %s" % (username, groups))
return groups
@staticmethod
def add_group(group):
ret = IPBoardManager.exec_xmlrpc('addGroup', group=group)
logger.info("Added IPBoard group %s" % group)
return ret
@staticmethod
def add_user_to_group(username, group):
ret = IPBoardManager.exec_xmlrpc('addUserToGroup', username=username, group=group)
logger.info("Added IPBoard user %s to group %s" % (username, group))
return ret
@staticmethod
def remove_user_from_group(username, group):
ret = IPBoardManager.exec_xmlrpc('removeUserFromGroup', username=username, group=group)
logger.info("Removed IPBoard user %s from group %s" % (username, group))
return ret
@staticmethod
def help_me():
ret = IPBoardManager.exec_xmlrpc('helpMe')
return ret
@staticmethod
def update_groups(username, groups):
logger.debug("Updating IPBoard user %s with groups %s" % (username, groups))
forum_groups = IPBoardManager.get_all_groups()
user_groups = set(IPBoardManager.get_user_groups(username))
act_groups = set([IPBoardManager._sanitize_groupname(g) for g in groups])
addgroups = act_groups - user_groups
remgroups = user_groups - act_groups
logger.info("Updating IPBoard groups for user %s - adding %s, removing %s" % (username, addgroups, remgroups))
for g in addgroups:
if g not in forum_groups:
IPBoardManager.add_group(g)
logger.debug("Adding user %s to IPBoard group %s" % (username, g))
IPBoardManager.add_user_to_group(username, g)
for g in remgroups:
logger.debug("Removing user %s from IPBoard group %s" % (username, g))
IPBoardManager.remove_user_from_group(username, g)
@staticmethod
def update_user_password(username, email, plain_password=None):
logger.debug("Settings new IPBoard password for user %s" % username)
if not plain_password:
plain_password = IPBoardManager.__generate_random_pass()
IPBoardManager.update_user(username, email, plain_password)
return plain_password

View File

@@ -1,102 +0,0 @@
from __future__ import unicode_literals
import logging
import os
from django.db import connections
from passlib.hash import bcrypt
logger = logging.getLogger(__name__)
class Ips4Manager:
SQL_ADD_USER = r"INSERT INTO core_members (name, email, members_pass_hash, members_pass_salt, " \
r"member_group_id) VALUES (%s, %s, %s, %s, %s)"
SQL_GET_ID = r"SELECT member_id FROM core_members WHERE name = %s"
SQL_UPDATE_PASSWORD = r"UPDATE core_members SET members_pass_hash = %s, members_pass_salt = %s WHERE name = %s"
SQL_DEL_USER = r"DELETE FROM core_members WHERE member_id = %s"
MEMBER_GROUP_ID = 3
@staticmethod
def add_user(username, email):
logger.debug("Adding new IPS4 user %s" % username)
plain_password = Ips4Manager.__generate_random_pass()
hash = bcrypt.encrypt(plain_password, rounds=13)
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
group = Ips4Manager.MEMBER_GROUP_ID
cursor = connections['ips4'].cursor()
cursor.execute(Ips4Manager.SQL_ADD_USER, [username, email, hash, salt, group])
member_id = Ips4Manager.get_user_id(username)
return username, plain_password, member_id
@staticmethod
def get_user_id(username):
cursor = connections['ips4'].cursor()
cursor.execute(Ips4Manager.SQL_GET_ID, [username])
row = cursor.fetchone()
if row is not None:
logger.debug("Got user id %s for username %s" % (row[0], username))
return row[0]
else:
logger.error("username %s not found. Unable to determine id." % username)
return None
@staticmethod
def __generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def delete_user(id):
logger.debug("Deleting IPS4 user id %s" % id)
try:
cursor = connections['ips4'].cursor()
cursor.execute(Ips4Manager.SQL_DEL_USER, [id])
logger.info("Deleted IPS4 user %s" % id)
return True
except:
logger.exception("Failed to delete IPS4 user id %s" % id)
return False
@staticmethod
def update_user_password(username):
logger.debug("Updating IPS4 user id %s password" % id)
if Ips4Manager.check_user(username):
plain_password = Ips4Manager.__generate_random_pass()
hash = bcrypt.encrypt(plain_password, rounds=13)
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
cursor = connections['ips4'].cursor()
cursor.execute(Ips4Manager.SQL_UPDATE_PASSWORD, [hash, salt, username])
return plain_password
else:
logger.error("Unable to update ips4 user %s password" % username)
return ""
@staticmethod
def check_user(username):
logger.debug("Checking IPS4 username %s" % username)
cursor = connections['ips4'].cursor()
cursor.execute(Ips4Manager.SQL_GET_ID, [username])
row = cursor.fetchone()
if row:
logger.debug("Found user %s on IPS4" % username)
return True
logger.debug("User %s not found on IPS4" % username)
return False
@staticmethod
def update_custom_password(username, plain_password):
logger.debug("Updating IPS4 user id %s password" % id)
if Ips4Manager.check_user(username):
hash = bcrypt.encrypt(plain_password, rounds=13)
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
cursor = connections['ips4'].cursor()
cursor.execute(Ips4Manager.SQL_UPDATE_PASSWORD, [hash, salt, username])
return plain_password
else:
logger.error("Unable to update ips4 user %s password" % username)
return ""

View File

@@ -1,145 +0,0 @@
from __future__ import unicode_literals
import logging
import os
from django.db import connections
from passlib.hash import bcrypt
# requires yum install libffi-devel and pip install bcrypt
logger = logging.getLogger(__name__)
class marketManager:
def __init__(self):
pass
SQL_ADD_USER = r"INSERT INTO fos_user (username, username_canonical, email, email_canonical, enabled, salt," \
r"password, locked, expired, roles, credentials_expired, characterid, characterName)" \
r"VALUES (%s, %s, %s, %s, 1,%s, %s, 0, 0, 'a:0:{}', 0, %s, %s) "
SQL_GET_USER_ID = r"SELECT id FROM fos_user WHERE username = %s"
SQL_DISABLE_USER = r"UPDATE fos_user SET enabled = '0' WHERE username = %s"
SQL_ENABLE_USER = r"UPDATE fos_user SET enabled = '1' WHERE username = %s"
SQL_UPDATE_PASSWORD = r"UPDATE fos_user SET password = %s, salt = %s WHERE username = %s"
SQL_CHECK_EMAIL = r"SELECT email FROM fos_user WHERE email = %s"
SQL_CHECK_USERNAME = r"SELECT username FROM fos_user WHERE username = %s"
SQL_UPDATE_USER = r"UPDATE fos_user SET password = %s, salt = %s, enabled = '1' WHERE username = %s"
@staticmethod
def __santatize_username(username):
sanatized = username.replace(" ", "_")
return sanatized.lower()
@staticmethod
def __generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def check_username(username):
logger.debug("Checking alliance market username %s" % username)
cursor = connections['market'].cursor()
cursor.execute(marketManager.SQL_CHECK_USERNAME, [marketManager.__santatize_username(username)])
row = cursor.fetchone()
if row:
logger.debug("Found user %s on alliance market" % username)
return True
logger.debug("User %s not found on alliance market" % username)
return False
@staticmethod
def check_user_email(username, email):
logger.debug("Checking if alliance market email exists for user %s" % username)
cursor = connections['market'].cursor()
cursor.execute(marketManager.SQL_CHECK_EMAIL, [email])
row = cursor.fetchone()
if row:
logger.debug("Found user %s email address on alliance market" % username)
return True
logger.debug("User %s email address not found on alliance market" % username)
return False
@staticmethod
def add_user(username, email, characterid, charactername):
logger.debug("Adding new market user %s" % username)
plain_password = marketManager.__generate_random_pass()
hash = bcrypt.encrypt(plain_password, rounds=13)
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
username_clean = marketManager.__santatize_username(username)
if not marketManager.check_username(username):
if not marketManager.check_user_email(username, email):
try:
logger.debug("Adding user %s to alliance market" % username)
cursor = connections['market'].cursor()
cursor.execute(marketManager.SQL_ADD_USER, [username_clean, username_clean, email, email, salt,
hash, characterid, charactername])
return username_clean, plain_password
except:
logger.debug("Unsuccessful attempt to add market user %s" % username)
return "", ""
else:
logger.debug("Alliance market email %s already exists Updating instead" % email)
username_clean, password = marketManager.update_user_info(username)
return username_clean, password
else:
logger.debug("Alliance market username %s already exists Updating instead" % username)
username_clean, password = marketManager.update_user_info(username)
return username_clean, password
@staticmethod
def disable_user(username):
logger.debug("Disabling alliance market user %s " % username)
cursor = connections['market'].cursor()
cursor.execute(marketManager.SQL_DISABLE_USER, [username])
return True
@staticmethod
def update_custom_password(username, plain_password):
logger.debug("Updating alliance market user %s password" % username)
if marketManager.check_username(username):
username_clean = marketManager.__santatize_username(username)
hash = bcrypt.encrypt(plain_password, rounds=13)
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
cursor = connections['market'].cursor()
cursor.execute(marketManager.SQL_UPDATE_PASSWORD, [hash, salt, username_clean])
return plain_password
else:
logger.error("Unable to update alliance market user %s password" % username)
return ""
@staticmethod
def update_user_password(username):
logger.debug("Updating alliance market user %s password" % username)
if marketManager.check_username(username):
username_clean = marketManager.__santatize_username(username)
plain_password = marketManager.__generate_random_pass()
hash = bcrypt.encrypt(plain_password, rounds=13)
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
cursor = connections['market'].cursor()
cursor.execute(marketManager.SQL_UPDATE_PASSWORD, [hash, salt, username_clean])
return plain_password
else:
logger.error("Unable to update alliance market user %s password" % username)
return ""
@staticmethod
def update_user_info(username):
logger.debug("Updating alliance market user %s" % username)
try:
username_clean = marketManager.__santatize_username(username)
plain_password = marketManager.__generate_random_pass()
hash = bcrypt.encrypt(plain_password, rounds=13)
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
cursor = connections['market'].cursor()
cursor.execute(marketManager.SQL_UPDATE_USER, [hash, salt, username_clean])
return username_clean, plain_password
except:
logger.debug("Alliance market update user failed for %s" % username)
return "", ""

View File

@@ -1,121 +0,0 @@
from __future__ import unicode_literals
import os
import hashlib
from services.models import MumbleUser
import logging
logger = logging.getLogger(__name__)
class MumbleManager:
def __init__(self):
pass
@staticmethod
def __santatize_username(username):
sanatized = username.replace(" ", "_")
return sanatized
@staticmethod
def __generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def __generate_username(username, corp_ticker):
return "[" + corp_ticker + "]" + username
@staticmethod
def __generate_username_blue(username, corp_ticker):
return "[BLUE][" + corp_ticker + "]" + username
@staticmethod
def _gen_pwhash(password):
return hashlib.sha1(password).hexdigest()
@staticmethod
def create_user(corp_ticker, username):
logger.debug("Creating mumble user with username %s and ticker %s" % (username, corp_ticker))
username_clean = MumbleManager.__santatize_username(MumbleManager.__generate_username(username, corp_ticker))
password = MumbleManager.__generate_random_pass()
pwhash = MumbleManager._gen_pwhash(password)
logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % (
username_clean, pwhash[0:5]))
if MumbleUser.objects.filter(username=username_clean).exists() is False:
logger.info("Creating mumble user %s" % username_clean)
MumbleUser.objects.create(username=username_clean, pwhash=pwhash)
return username_clean, password
else:
logger.warn("Mumble user %s already exists. Updating password")
model = MumbleUser.objects.get(username=username_clean)
model.pwhash = pwhash
model.save()
logger.info("Updated mumble user %s" % username_clean)
return username_clean, password
@staticmethod
def create_blue_user(corp_ticker, username):
logger.debug("Creating mumble blue user with username %s and ticker %s" % (username, corp_ticker))
username_clean = MumbleManager.__santatize_username(
MumbleManager.__generate_username_blue(username, corp_ticker))
password = MumbleManager.__generate_random_pass()
pwhash = MumbleManager._gen_pwhash(password)
logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % (
username_clean, pwhash[0:5]))
if MumbleUser.objects.filter(username=username_clean).exists() is False:
logger.info("Creating mumble user %s" % username_clean)
MumbleUser.objects.create(username=username_clean, pwhash=pwhash)
return username_clean, password
else:
logger.warn("Mumble user %s already exists. Updating password")
model = MumbleUser.objects.get(username=username_clean)
model.pwhash = pwhash
model.save()
logger.info("Updated mumble user %s" % username_clean)
return username_clean, password
@staticmethod
def delete_user(username):
logger.debug("Deleting user %s from mumble." % username)
if MumbleUser.objects.filter(username=username).exists():
MumbleUser.objects.filter(username=username).delete()
logger.info("Deleted user %s from mumble" % username)
return True
logger.error("Unable to delete user %s from mumble: MumbleUser model not found" % username)
return False
@staticmethod
def update_user_password(username, password=None):
logger.debug("Updating mumble user %s password." % username)
if not password:
password = MumbleManager.__generate_random_pass()
pwhash = MumbleManager._gen_pwhash(password)
logger.debug("Proceeding with mumble user %s password update - pwhash starts with %s" % (username, pwhash[0:5]))
if MumbleUser.objects.filter(username=username).exists():
model = MumbleUser.objects.get(username=username)
model.pwhash = pwhash
model.save()
return password
logger.error("User %s not found on mumble. Unable to update password." % username)
return ""
@staticmethod
def update_groups(username, groups):
logger.debug("Updating mumble user %s groups %s" % (username, groups))
safe_groups = list(set([g.replace(' ', '-') for g in groups]))
groups = ''
for g in safe_groups:
groups = groups + g + ','
groups = groups.strip(',')
if MumbleUser.objects.filter(username=username).exists():
logger.info("Updating mumble user %s groups to %s" % (username, safe_groups))
model = MumbleUser.objects.get(username=username)
model.groups = groups
model.save()
else:
logger.error("User %s not found on mumble. Unable to update groups." % username)
@staticmethod
def user_exists(username):
return MumbleUser.objects.filter(username=username).exists()

View File

@@ -1,200 +0,0 @@
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)

View File

@@ -1,301 +0,0 @@
from __future__ import unicode_literals
import os
import calendar
import re
from datetime import datetime
from passlib.apps import phpbb3_context
from django.db import connections
import logging
from django.conf import settings
logger = logging.getLogger(__name__)
class Phpbb3Manager:
SQL_ADD_USER = r"INSERT INTO phpbb_users (username, username_clean, " \
r"user_password, user_email, group_id, user_regdate, user_permissions, " \
r"user_sig) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"
SQL_DEL_USER = r"DELETE FROM phpbb_users where username = %s"
SQL_DIS_USER = r"UPDATE phpbb_users SET user_email= %s, user_password=%s WHERE username = %s"
SQL_USER_ID_FROM_USERNAME = r"SELECT user_id from phpbb_users WHERE username = %s"
SQL_ADD_USER_GROUP = r"INSERT INTO phpbb_user_group (group_id, user_id, user_pending) VALUES (%s, %s, %s)"
SQL_GET_GROUP_ID = r"SELECT group_id from phpbb_groups WHERE group_name = %s"
SQL_ADD_GROUP = r"INSERT INTO phpbb_groups (group_name,group_desc,group_legend) VALUES (%s,%s,0)"
SQL_UPDATE_USER_PASSWORD = r"UPDATE phpbb_users SET user_password = %s WHERE username = %s"
SQL_REMOVE_USER_GROUP = r"DELETE FROM phpbb_user_group WHERE user_id=%s AND group_id=%s "
SQL_GET_ALL_GROUPS = r"SELECT group_id, group_name FROM phpbb_groups"
SQL_GET_USER_GROUPS = r"SELECT phpbb_groups.group_name FROM phpbb_groups , phpbb_user_group WHERE " \
r"phpbb_user_group.group_id = phpbb_groups.group_id AND user_id=%s"
SQL_ADD_USER_AVATAR = r"UPDATE phpbb_users SET user_avatar_type=2, user_avatar_width=64, user_avatar_height=64, " \
"user_avatar=%s WHERE user_id = %s"
SQL_CLEAR_USER_PERMISSIONS = r"UPDATE phpbb_users SET user_permissions = '' WHERE user_Id = %s"
SQL_DEL_SESSION = r"DELETE FROM phpbb_sessions where session_user_id = %s"
SQL_DEL_AUTOLOGIN = r"DELETE FROM phpbb_sessions_keys where user_id = %s"
def __init__(self):
pass
@staticmethod
def __add_avatar(username, characterid):
logger.debug("Adding EVE character id %s portrait as phpbb avater for user %s" % (characterid, username))
avatar_url = "https://image.eveonline.com/Character/" + characterid + "_64.jpg"
cursor = connections['phpbb3'].cursor()
userid = Phpbb3Manager.__get_user_id(username)
cursor.execute(Phpbb3Manager.SQL_ADD_USER_AVATAR, [avatar_url, userid])
@staticmethod
def __generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def __gen_hash(password):
return phpbb3_context.encrypt(password)
@staticmethod
def __santatize_username(username):
sanatized = username.replace(" ", "_")
sanatized = sanatized.replace("'", "_")
return sanatized.lower()
@staticmethod
def _sanitize_groupname(name):
name = name.strip(' _')
return re.sub('[^\w.-]', '', name)
@staticmethod
def __get_group_id(groupname):
logger.debug("Getting phpbb3 group id for groupname %s" % groupname)
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_GET_GROUP_ID, [groupname])
row = cursor.fetchone()
logger.debug("Got phpbb group id %s for groupname %s" % (row[0], groupname))
return row[0]
@staticmethod
def __get_user_id(username):
logger.debug("Getting phpbb3 user id for username %s" % username)
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_USER_ID_FROM_USERNAME, [username])
row = cursor.fetchone()
if row is not None:
logger.debug("Got phpbb user id %s for username %s" % (row[0], username))
return row[0]
else:
logger.error("Username %s not found on phpbb. Unable to determine user id." % username)
return None
@staticmethod
def __get_all_groups():
logger.debug("Getting all phpbb3 groups.")
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_GET_ALL_GROUPS)
rows = cursor.fetchall()
out = {}
for row in rows:
out[row[1]] = row[0]
logger.debug("Got phpbb groups %s" % out)
return out
@staticmethod
def __get_user_groups(userid):
logger.debug("Getting phpbb3 user id %s groups" % userid)
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_GET_USER_GROUPS, [userid])
out = [row[0] for row in cursor.fetchall()]
logger.debug("Got user %s phpbb groups %s" % (userid, out))
return out
@staticmethod
def __get_current_utc_date():
d = datetime.utcnow()
unixtime = calendar.timegm(d.utctimetuple())
return unixtime
@staticmethod
def __create_group(groupname):
logger.debug("Creating phpbb3 group %s" % groupname)
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_ADD_GROUP, [groupname, groupname])
logger.info("Created phpbb group %s" % groupname)
return Phpbb3Manager.__get_group_id(groupname)
@staticmethod
def __add_user_to_group(userid, groupid):
logger.debug("Adding phpbb3 user id %s to group id %s" % (userid, groupid))
try:
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_ADD_USER_GROUP, [groupid, userid, 0])
cursor.execute(Phpbb3Manager.SQL_CLEAR_USER_PERMISSIONS, [userid])
logger.info("Added phpbb user id %s to group id %s" % (userid, groupid))
except:
logger.exception("Unable to add phpbb user id %s to group id %s" % (userid, groupid))
pass
@staticmethod
def __remove_user_from_group(userid, groupid):
logger.debug("Removing phpbb3 user id %s from group id %s" % (userid, groupid))
try:
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_REMOVE_USER_GROUP, [userid, groupid])
cursor.execute(Phpbb3Manager.SQL_CLEAR_USER_PERMISSIONS, [userid])
logger.info("Removed phpbb user id %s from group id %s" % (userid, groupid))
except:
logger.exception("Unable to remove phpbb user id %s from group id %s" % (userid, groupid))
pass
@staticmethod
def add_user(username, email, groups, characterid):
logger.debug("Adding phpbb user with username %s, email %s, groups %s, characterid %s" % (
username, email, groups, characterid))
cursor = connections['phpbb3'].cursor()
username_clean = Phpbb3Manager.__santatize_username(username)
password = Phpbb3Manager.__generate_random_pass()
pwhash = Phpbb3Manager.__gen_hash(password)
logger.debug("Proceeding to add phpbb user %s and pwhash starting with %s" % (username_clean, pwhash[0:5]))
# check if the username was simply revoked
if Phpbb3Manager.check_user(username_clean):
logger.warn("Unable to add phpbb user with username %s - already exists. Updating user instead." % username)
Phpbb3Manager.__update_user_info(username_clean, email, pwhash)
else:
try:
cursor.execute(Phpbb3Manager.SQL_ADD_USER, [username_clean, username_clean, pwhash,
email, 2, Phpbb3Manager.__get_current_utc_date(),
"", ""])
Phpbb3Manager.update_groups(username_clean, groups)
Phpbb3Manager.__add_avatar(username_clean, characterid)
logger.info("Added phpbb user %s" % username_clean)
except:
logger.exception("Unable to add phpbb user %s" % username_clean)
pass
return username_clean, password
@staticmethod
def disable_user(username):
logger.debug("Disabling phpbb user %s" % username)
cursor = connections['phpbb3'].cursor()
password = Phpbb3Manager.__gen_hash(Phpbb3Manager.__generate_random_pass())
revoke_email = "revoked@" + settings.DOMAIN
try:
pwhash = Phpbb3Manager.__gen_hash(password)
cursor.execute(Phpbb3Manager.SQL_DIS_USER, [revoke_email, pwhash, username])
userid = Phpbb3Manager.__get_user_id(username)
cursor.execute(Phpbb3Manager.SQL_DEL_AUTOLOGIN, [userid])
cursor.execute(Phpbb3Manager.SQL_DEL_SESSION, [userid])
Phpbb3Manager.update_groups(username, [])
logger.info("Disabled phpbb user %s" % username)
return True
except TypeError:
logger.exception("TypeError occured while disabling user %s - failed to disable." % username)
return False
@staticmethod
def delete_user(username):
logger.debug("Deleting phpbb user %s" % username)
cursor = connections['phpbb3'].cursor()
if Phpbb3Manager.check_user(username):
cursor.execute(Phpbb3Manager.SQL_DEL_USER, [username])
logger.info("Deleted phpbb user %s" % username)
return True
logger.error("Unable to delete phpbb user %s - user not found on phpbb." % username)
return False
@staticmethod
def update_groups(username, groups):
userid = Phpbb3Manager.__get_user_id(username)
logger.debug("Updating phpbb user %s with id %s groups %s" % (username, userid, groups))
if userid is not None:
forum_groups = Phpbb3Manager.__get_all_groups()
user_groups = set(Phpbb3Manager.__get_user_groups(userid))
act_groups = set([Phpbb3Manager._sanitize_groupname(g) for g in groups])
addgroups = act_groups - user_groups
remgroups = user_groups - act_groups
logger.info("Updating phpbb user %s groups - adding %s, removing %s" % (username, addgroups, remgroups))
for g in addgroups:
if not g in forum_groups:
forum_groups[g] = Phpbb3Manager.__create_group(g)
Phpbb3Manager.__add_user_to_group(userid, forum_groups[g])
for g in remgroups:
Phpbb3Manager.__remove_user_from_group(userid, forum_groups[g])
@staticmethod
def remove_group(username, group):
logger.debug("Removing phpbb user %s from group %s" % (username, group))
cursor = connections['phpbb3'].cursor()
userid = Phpbb3Manager.__get_user_id(username)
if userid is not None:
groupid = Phpbb3Manager.__get_group_id(group)
if userid:
if groupid:
try:
cursor.execute(Phpbb3Manager.SQL_REMOVE_USER_GROUP, [userid, groupid])
logger.info("Removed phpbb user %s from group %s" % (username, group))
except:
logger.exception(
"Exception prevented removal of phpbb user %s with id %s from group %s with id %s" % (
username, userid, group, groupid))
pass
@staticmethod
def check_user(username):
logger.debug("Checking phpbb username %s" % username)
cursor = connections['phpbb3'].cursor()
cursor.execute(Phpbb3Manager.SQL_USER_ID_FROM_USERNAME, [Phpbb3Manager.__santatize_username(username)])
row = cursor.fetchone()
if row:
logger.debug("Found user %s on phpbb" % username)
return True
logger.debug("User %s not found on phpbb" % username)
return False
@staticmethod
def update_user_password(username, characterid, password=None):
logger.debug("Updating phpbb user %s password" % username)
cursor = connections['phpbb3'].cursor()
if not password:
password = Phpbb3Manager.__generate_random_pass()
if Phpbb3Manager.check_user(username):
pwhash = Phpbb3Manager.__gen_hash(password)
logger.debug(
"Proceeding to update phpbb user %s password with pwhash starting with %s" % (username, pwhash[0:5]))
cursor.execute(Phpbb3Manager.SQL_UPDATE_USER_PASSWORD, [pwhash, username])
Phpbb3Manager.__add_avatar(username, characterid)
logger.info("Updated phpbb user %s password." % username)
return password
logger.error("Unable to update phpbb user %s password - user not found on phpbb." % username)
return ""
@staticmethod
def __update_user_info(username, email, password):
logger.debug(
"Updating phpbb user %s info: username %s password of length %s" % (username, email, len(password)))
cursor = connections['phpbb3'].cursor()
try:
cursor.execute(Phpbb3Manager.SQL_DIS_USER, [email, password, username])
logger.info("Updated phpbb user %s info" % username)
except:
logger.exception("Unable to update phpbb user %s info." % username)
pass

View File

@@ -1,266 +0,0 @@
from __future__ import unicode_literals
import os
import calendar
from datetime import datetime
import hashlib
import logging
import re
from django.db import connections
from django.conf import settings
logger = logging.getLogger(__name__)
class smfManager:
def __init__(self):
pass
SQL_ADD_USER = r"INSERT INTO smf_members (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)"
SQL_DEL_USER = r"DELETE FROM smf_members where member_name = %s"
SQL_DIS_USER = r"UPDATE smf_members SET email_address = %s, passwd = %s WHERE member_name = %s"
SQL_USER_ID_FROM_USERNAME = r"SELECT id_member from smf_members WHERE member_name = %s"
SQL_ADD_USER_GROUP = r"UPDATE smf_members SET additional_groups = %s WHERE id_member = %s"
SQL_GET_GROUP_ID = r"SELECT id_group from smf_membergroups WHERE group_name = %s"
SQL_ADD_GROUP = r"INSERT INTO smf_membergroups (group_name,description) VALUES (%s,%s)"
SQL_UPDATE_USER_PASSWORD = r"UPDATE smf_members SET passwd = %s WHERE member_name = %s"
SQL_REMOVE_USER_GROUP = r"UPDATE smf_members SET additional_groups = %s WHERE id_member = %s"
SQL_GET_ALL_GROUPS = r"SELECT id_group, group_name FROM smf_membergroups"
SQL_GET_USER_GROUPS = r"SELECT additional_groups FROM smf_members WHERE id_member = %s"
SQL_ADD_USER_AVATAR = r"UPDATE smf_members SET avatar = %s WHERE id_member = %s"
@staticmethod
def _sanitize_groupname(name):
name = name.strip(' _')
return re.sub('[^\w.-]', '', name)
@staticmethod
def generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def gen_hash(username_clean, passwd):
return hashlib.sha1(username_clean + passwd).hexdigest()
@staticmethod
def santatize_username(username):
sanatized = username.replace(" ", "_")
sanatized = sanatized.replace("'", "_")
return sanatized.lower()
@staticmethod
def get_current_utc_date():
d = datetime.utcnow()
unixtime = calendar.timegm(d.utctimetuple())
return unixtime
@staticmethod
def create_group(groupname):
logger.debug("Creating smf group %s" % groupname)
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_ADD_GROUP, [groupname, groupname])
logger.info("Created smf group %s" % groupname)
return smfManager.get_group_id(groupname)
@staticmethod
def get_group_id(groupname):
logger.debug("Getting smf group id for groupname %s" % groupname)
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_GET_GROUP_ID, [groupname])
row = cursor.fetchone()
logger.debug("Got smf group id %s for groupname %s" % (row[0], groupname))
return row[0]
@staticmethod
def check_user(username):
logger.debug("Checking smf username %s" % username)
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_USER_ID_FROM_USERNAME, [smfManager.santatize_username(username)])
row = cursor.fetchone()
if row:
logger.debug("Found user %s on smf" % username)
return True
logger.debug("User %s not found on smf" % username)
return False
@staticmethod
def add_avatar(member_name, characterid):
logger.debug("Adding EVE character id %s portrait as smf avatar for user %s" % (characterid, member_name))
avatar_url = "https://image.eveonline.com/Character/" + characterid + "_64.jpg"
cursor = connections['smf'].cursor()
id_member = smfManager.get_user_id(member_name)
cursor.execute(smfManager.SQL_ADD_USER_AVATAR, [avatar_url, id_member])
@staticmethod
def get_user_id(username):
logger.debug("Getting smf user id for username %s" % username)
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_USER_ID_FROM_USERNAME, [username])
row = cursor.fetchone()
if row is not None:
logger.debug("Got smf user id %s for username %s" % (row[0], username))
return row[0]
else:
logger.error("username %s not found on smf. Unable to determine user id ." % username)
return None
@staticmethod
def get_all_groups():
logger.debug("Getting all smf groups.")
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_GET_ALL_GROUPS)
rows = cursor.fetchall()
out = {}
for row in rows:
out[row[1]] = row[0]
logger.debug("Got smf groups %s" % out)
return out
@staticmethod
def get_user_groups(userid):
logger.debug("Getting smf user id %s groups" % userid)
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_GET_USER_GROUPS, [userid])
out = [row[0] for row in cursor.fetchall()]
logger.debug("Got user %s smf groups %s" % (userid, out))
return out
@staticmethod
def add_user(username, email_address, groups, characterid):
logger.debug("Adding smf user with member_name %s, email_address %s, characterid %s" % (
username, email_address, characterid))
cursor = connections['smf'].cursor()
username_clean = smfManager.santatize_username(username)
passwd = smfManager.generate_random_pass()
pwhash = smfManager.gen_hash(username_clean, passwd)
logger.debug("Proceeding to add smf user %s and pwhash starting with %s" % (username, pwhash[0:5]))
register_date = smfManager.get_current_utc_date()
# check if the username was simply revoked
if smfManager.check_user(username) is True:
logger.warn("Unable to add smf user with username %s - already exists. Updating user instead." % username)
smfManager.__update_user_info(username_clean, email_address, pwhash)
else:
try:
cursor.execute(smfManager.SQL_ADD_USER,
[username_clean, passwd, email_address, register_date, username_clean])
smfManager.add_avatar(username_clean, characterid)
logger.info("Added smf member_name %s" % username_clean)
smfManager.update_groups(username_clean, groups)
except:
logger.warn("Unable to add smf user %s" % username_clean)
pass
return username_clean, passwd
@staticmethod
def __update_user_info(username, email_address, passwd):
logger.debug(
"Updating smf user %s info: username %s password of length %s" % (username, email_address, len(passwd)))
cursor = connections['smf'].cursor()
try:
cursor.execute(smfManager.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)
pass
@staticmethod
def delete_user(username):
logger.debug("Deleting smf user %s" % username)
cursor = connections['smf'].cursor()
if smfManager.check_user(username):
cursor.execute(smfManager.SQL_DEL_USER, [username])
logger.info("Deleted smf user %s" % username)
return True
logger.error("Unable to delete smf user %s - user not found on smf." % username)
return False
@staticmethod
def update_groups(username, groups):
userid = smfManager.get_user_id(username)
logger.debug("Updating smf user %s with id %s groups %s" % (username, userid, groups))
if userid is not None:
forum_groups = smfManager.get_all_groups()
user_groups = set(smfManager.get_user_groups(userid))
act_groups = set([smfManager._sanitize_groupname(g) for g in groups])
addgroups = act_groups - user_groups
remgroups = user_groups - act_groups
logger.info("Updating smf user %s groups - adding %s, removing %s" % (username, addgroups, remgroups))
act_group_id = set()
for g in addgroups:
if g not in forum_groups:
forum_groups[g] = smfManager.create_group(g)
act_group_id.add(str(smfManager.get_group_id(g)))
string_groups = ','.join(act_group_id)
smfManager.add_user_to_group(userid, string_groups)
@staticmethod
def add_user_to_group(userid, groupid):
logger.debug("Adding smf user id %s to group id %s" % (userid, groupid))
try:
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_ADD_USER_GROUP, [groupid, userid])
logger.info("Added smf user id %s to group id %s" % (userid, groupid))
except:
logger.exception("Unable to add smf user id %s to group id %s" % (userid, groupid))
pass
@staticmethod
def remove_user_from_group(userid, groupid):
logger.debug("Removing smf user id %s from group id %s" % (userid, groupid))
try:
cursor = connections['smf'].cursor()
cursor.execute(smfManager.SQL_REMOVE_USER_GROUP, [groupid, userid])
logger.info("Removed smf user id %s from group id %s" % (userid, groupid))
except:
logger.exception("Unable to remove smf user id %s from group id %s" % (userid, groupid))
pass
@staticmethod
def disable_user(username):
logger.debug("Disabling smf user %s" % username)
cursor = connections['smf'].cursor()
password = smfManager.generate_random_pass()
revoke_email = "revoked@" + settings.DOMAIN
try:
pwhash = smfManager.gen_hash(username, password)
cursor.execute(smfManager.SQL_DIS_USER, [revoke_email, pwhash, username])
smfManager.get_user_id(username)
smfManager.update_groups(username, [])
logger.info("Disabled smf user %s" % username)
return True
except TypeError:
logger.exception("TypeError occured while disabling user %s - failed to disable." % username)
return False
@staticmethod
def update_user_password(username, characterid, password=None):
logger.debug("Updating smf user %s password" % username)
cursor = connections['smf'].cursor()
if not password:
password = smfManager.generate_random_pass()
if smfManager.check_user(username):
username_clean = smfManager.santatize_username(username)
pwhash = smfManager.gen_hash(username_clean, password)
logger.debug(
"Proceeding to update smf user %s password with pwhash starting with %s" % (username, pwhash[0:5]))
cursor.execute(smfManager.SQL_UPDATE_USER_PASSWORD, [pwhash, username])
smfManager.add_avatar(username, characterid)
logger.info("Updated smf user %s password." % username)
return password
logger.error("Unable to update smf user %s password - user not found on smf." % username)
return ""

View File

@@ -1,314 +0,0 @@
from __future__ import unicode_literals
from django.conf import settings
from services.managers.util.ts3 import TS3Server, TeamspeakError
from services.models import TSgroup
import logging
logger = logging.getLogger(__name__)
class Teamspeak3Manager:
def __init__(self):
pass
@staticmethod
def __get_created_server():
server = TS3Server(settings.TEAMSPEAK3_SERVER_IP, settings.TEAMSPEAK3_SERVER_PORT)
server.login(settings.TEAMSPEAK3_SERVERQUERY_USER, settings.TEAMSPEAK3_SERVERQUERY_PASSWORD)
server.use(settings.TEAMSPEAK3_VIRTUAL_SERVER)
logger.debug("Got TS3 server instance based on settings.")
return server
@staticmethod
def __santatize_username(username):
sanatized = username.replace(" ", "_")
sanatized = sanatized.replace("'", "-")
return sanatized
@staticmethod
def __generate_username(username, corp_ticker):
sanatized = "[" + corp_ticker + "]" + username
return sanatized[:30]
@staticmethod
def __generate_username_blue(username, corp_ticker):
sanatized = "[BLUE][" + corp_ticker + "]" + username
return sanatized[:30]
@staticmethod
def _get_userid(uid):
logger.debug("Looking for uid %s on TS3 server." % uid)
server = Teamspeak3Manager.__get_created_server()
try:
ret = server.send_command('customsearch', {'ident': 'sso_uid', 'pattern': uid})
if ret and 'keys' in ret and 'cldbid' in ret['keys']:
logger.debug("Got userid %s for uid %s" % (ret['keys']['cldbid'], uid))
return ret['keys']['cldbid']
except TeamspeakError as e:
if not e.code == '1281':
raise e
return None
@staticmethod
def _group_id_by_name(groupname):
server = Teamspeak3Manager.__get_created_server()
logger.debug("Looking for group %s on TS3 server." % groupname)
group_cache = server.send_command('servergrouplist')
logger.debug("Received group cache from server: %s" % group_cache)
for group in group_cache:
logger.debug("Checking group %s" % group)
if group['keys']['name'] == groupname:
logger.debug("Found group %s, returning id %s" % (groupname, group['keys']['sgid']))
return group['keys']['sgid']
logger.debug("Group %s not found on server." % groupname)
return None
@staticmethod
def _create_group(groupname):
logger.debug("Creating group %s on TS3 server." % groupname)
server = Teamspeak3Manager.__get_created_server()
sgid = Teamspeak3Manager._group_id_by_name(groupname)
if not sgid:
logger.debug("Group does not yet exist. Proceeding with creation.")
ret = server.send_command('servergroupadd', {'name': groupname})
Teamspeak3Manager.__group_cache = None
sgid = ret['keys']['sgid']
server.send_command('servergroupaddperm',
{'sgid': sgid, 'permsid': 'i_group_needed_modify_power', 'permvalue': 75,
'permnegated': 0, 'permskip': 0})
server.send_command('servergroupaddperm',
{'sgid': sgid, 'permsid': 'i_group_needed_member_add_power', 'permvalue': 100,
'permnegated': 0, 'permskip': 0})
server.send_command('servergroupaddperm',
{'sgid': sgid, 'permsid': 'i_group_needed_member_remove_power', 'permvalue': 100,
'permnegated': 0, 'permskip': 0})
logger.info("Created group on TS3 server with name %s and id %s" % (groupname, sgid))
return sgid
@staticmethod
def _user_group_list(cldbid):
logger.debug("Retrieving group list for user with id %s" % cldbid)
server = Teamspeak3Manager.__get_created_server()
try:
groups = server.send_command('servergroupsbyclientid', {'cldbid': cldbid})
except TeamspeakError as e:
if e.code == '1281': # no groups
groups = []
else:
raise e
logger.debug("Retrieved group list: %s" % groups)
outlist = {}
if type(groups) == list:
logger.debug("Recieved multiple groups. Iterating.")
for group in groups:
outlist[group['keys']['name']] = group['keys']['sgid']
elif type(groups) == dict:
logger.debug("Recieved single group.")
outlist[groups['keys']['name']] = groups['keys']['sgid']
logger.debug("Returning name/id pairing: %s" % outlist)
return outlist
@staticmethod
def _group_list():
logger.debug("Retrieving group list on TS3 server.")
server = Teamspeak3Manager.__get_created_server()
group_cache = server.send_command('servergrouplist')
logger.debug("Received group cache from server: %s" % group_cache)
outlist = {}
if group_cache:
for group in group_cache:
logger.debug("Assigning name/id dict: %s = %s" % (group['keys']['name'], group['keys']['sgid']))
outlist[group['keys']['name']] = group['keys']['sgid']
else:
logger.error("Received empty group cache while retrieving group cache from TS3 server. 1024 error.")
logger.debug("Returning name/id pairing: %s" % outlist)
return outlist
@staticmethod
def _add_user_to_group(uid, groupid):
logger.debug("Adding group id %s to TS3 user id %s" % (groupid, uid))
server = Teamspeak3Manager.__get_created_server()
user_groups = Teamspeak3Manager._user_group_list(uid)
if groupid not in user_groups.values():
logger.debug("User does not have group already. Issuing command to add.")
server.send_command('servergroupaddclient',
{'sgid': str(groupid), 'cldbid': uid})
logger.info("Added user id %s to group id %s on TS3 server." % (uid, groupid))
@staticmethod
def _remove_user_from_group(uid, groupid):
logger.debug("Removing group id %s from TS3 user id %s" % (groupid, uid))
server = Teamspeak3Manager.__get_created_server()
user_groups = Teamspeak3Manager._user_group_list(uid)
if str(groupid) in user_groups.values():
logger.debug("User is in group. Issuing command to remove.")
server.send_command('servergroupdelclient',
{'sgid': str(groupid), 'cldbid': uid})
logger.info("Removed user id %s from group id %s on TS3 server." % (uid, groupid))
@staticmethod
def _sync_ts_group_db():
logger.debug("_sync_ts_group_db function called.")
try:
remote_groups = Teamspeak3Manager._group_list()
local_groups = TSgroup.objects.all()
logger.debug("Comparing remote groups to TSgroup objects: %s" % local_groups)
for key in remote_groups:
logger.debug("Typecasting remote_group value at position %s to int: %s" % (key, remote_groups[key]))
remote_groups[key] = int(remote_groups[key])
for group in local_groups:
logger.debug("Checking local group %s" % group)
if group.ts_group_id not in remote_groups.values():
logger.debug(
"Local group id %s not found on server. Deleting model %s" % (group.ts_group_id, group))
TSgroup.objects.filter(ts_group_id=group.ts_group_id).delete()
for key in remote_groups:
g = TSgroup(ts_group_id=remote_groups[key], ts_group_name=key)
q = TSgroup.objects.filter(ts_group_id=g.ts_group_id)
if not q:
logger.debug("Local group does not exist for TS group %s. Creating TSgroup model %s" % (
remote_groups[key], g))
g.save()
except TeamspeakError as e:
logger.error("Error occured while syncing TS group db: %s" % str(e))
except:
logger.exception("An unhandled exception has occured while syncing TS groups.")
@staticmethod
def add_user(username, corp_ticker):
username_clean = Teamspeak3Manager.__santatize_username(Teamspeak3Manager.__generate_username(username,
corp_ticker))
server = Teamspeak3Manager.__get_created_server()
logger.debug("Adding user to TS3 server with cleaned username %s" % username_clean)
server_groups = Teamspeak3Manager._group_list()
if settings.DEFAULT_AUTH_GROUP not in server_groups:
Teamspeak3Manager._create_group(settings.DEFAULT_AUTH_GROUP)
alliance_group_id = Teamspeak3Manager._group_id_by_name(settings.DEFAULT_AUTH_GROUP)
try:
ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': alliance_group_id, 'tokenid2': 0,
'tokendescription': username_clean,
'tokencustomset': "ident=sso_uid value=%s" % username_clean})
except TeamspeakError as e:
logger.error("Failed to add teamspeak user %s: %s" % (username, str(e)))
return "",""
try:
token = ret['keys']['token']
logger.info("Created permission token for user %s on TS3 server" % username_clean)
return username_clean, token
except:
logger.exception("Failed to add teamspeak user %s - received response: %s" % (username_clean, ret))
return "", ""
@staticmethod
def add_blue_user(username, corp_ticker):
username_clean = Teamspeak3Manager.__santatize_username(Teamspeak3Manager.__generate_username_blue(username,
corp_ticker))
server = Teamspeak3Manager.__get_created_server()
logger.debug("Adding user to TS3 server with cleaned username %s" % username_clean)
server_groups = Teamspeak3Manager._group_list()
if settings.DEFAULT_BLUE_GROUP not in server_groups:
Teamspeak3Manager._create_group(settings.DEFAULT_BLUE_GROUP)
blue_group_id = Teamspeak3Manager._group_id_by_name(settings.DEFAULT_BLUE_GROUP)
try:
ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': blue_group_id, 'tokenid2': 0,
'tokendescription': username_clean,
'tokencustomset': "ident=sso_uid value=%s" % username_clean})
except TeamspeakError as e:
logger.error("Failed to add blue teamspeak user %s: %s" % (username, str(e)))
return "",""
try:
token = ret['keys']['token']
logger.info("Created permission token for blue user %s on TS3 server" % username_clean)
return username_clean, token
except:
logger.exception("Failed to add blue teamspeak user %s - received response: %s" % (username_clean, ret))
return "", ""
@staticmethod
def delete_user(uid):
server = Teamspeak3Manager.__get_created_server()
user = Teamspeak3Manager._get_userid(uid)
logger.debug("Deleting user %s with id %s from TS3 server." % (user, uid))
if user:
clients = server.send_command('clientlist')
for client in clients:
try:
if client['keys']['client_database_id'] == user:
logger.debug("Found user %s on TS3 server - issuing deletion command." % user)
server.send_command('clientkick', {'clid': client['keys']['clid'], 'reasonid': 5,
'reasonmsg': 'Auth service deleted'})
except:
logger.exception("Failed to delete user id %s from TS3 - received response %s" % (uid, client))
return False
try:
ret = server.send_command('clientdbdelete', {'cldbid': user})
except TeamspeakError as e:
logger.error("Failed to delete teamspeak user %s: %s" % (uid, str(e)))
return False
if ret == '0':
logger.info("Deleted user with id %s from TS3 server." % uid)
return True
else:
logger.exception("Failed to delete user id %s from TS3 - received response %s" % (uid, ret))
return False
else:
logger.warn("User with id %s not found on TS3 server. Assuming succesful deletion." % uid)
return True
@staticmethod
def check_user_exists(uid):
if Teamspeak3Manager._get_userid(uid):
return True
return False
@staticmethod
def generate_new_permissionkey(uid, username, corpticker):
logger.debug("Re-issuing permission key for user id %s" % uid)
Teamspeak3Manager.delete_user(uid)
return Teamspeak3Manager.add_user(username, corpticker)
@staticmethod
def generate_new_blue_permissionkey(uid, username, corpticker):
logger.debug("Re-issuing blue permission key for user id %s" % uid)
Teamspeak3Manager.delete_user(uid)
return Teamspeak3Manager.add_blue_user(username, corpticker)
@staticmethod
def update_groups(uid, ts_groups):
logger.debug("Updating uid %s TS3 groups %s" % (uid, ts_groups))
userid = Teamspeak3Manager._get_userid(uid)
addgroups = []
remgroups = []
if userid is not None:
user_ts_groups = Teamspeak3Manager._user_group_list(userid)
logger.debug("User has groups on TS3 server: %s" % user_ts_groups)
for key in user_ts_groups:
user_ts_groups[key] = int(user_ts_groups[key])
for ts_group_key in ts_groups:
logger.debug("Checking if user has group %s on TS3 server." % ts_group_key)
if ts_groups[ts_group_key] not in user_ts_groups.values():
addgroups.append(ts_groups[ts_group_key])
for user_ts_group_key in user_ts_groups:
if user_ts_groups[user_ts_group_key] not in ts_groups.values():
remgroups.append(user_ts_groups[user_ts_group_key])
for g in addgroups:
logger.info("Adding Teamspeak user %s into group %s" % (userid, g))
Teamspeak3Manager._add_user_to_group(userid, g)
for g in remgroups:
logger.info("Removing Teamspeak user %s from group %s" % (userid, g))
Teamspeak3Manager._remove_user_from_group(userid, g)

View File

@@ -1,2 +0,0 @@
from __future__ import unicode_literals
__author__ = 'r4stl1n'

View File

@@ -1,459 +0,0 @@
from __future__ import unicode_literals
import socket
import logging
class ConnectionError:
def __init__(self, ip, port):
self.ip = ip
self.port = port
def __str__(self):
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 'command' not in resp:
data.append(resp)
else:
break
if resp['command'] == 'error':
if resp['keys']['id'] == '0':
if data:
if len(data) > 1:
return data
else:
return data[0]
else:
return resp['keys']['id']
else:
raise TeamspeakError(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 not v == ['']:
if v[0][0] and 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.items():
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.items():
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 msg: 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})
class TeamspeakError(Exception):
def __init__(self, code, msg=None):
self.code = str(code)
if not msg:
msg = ts3_errors[self.code]
self.msg = msg
def __str__(self):
return self.code + ' ' + self.msg
ts3_errors = {
'0': 'unknown error code',
'1': 'undefined error',
'2': 'not implemented',
'3': '',
'4': '',
'5': 'library time limit reached',
'256': 'command not found',
'257': 'unable to bind network port',
'258': 'no network port available',
'512': 'invalid clientID',
'513': 'nickname is already in use',
'514': 'invalid error code',
'515': 'max clients protocol limit reached',
'516': 'invalid client type',
'517': 'already subscribed',
'518': 'not logged in',
'519': 'could not validate client identity',
'520': 'invalid loginname or password',
'521': 'too many clones already connected',
'522': 'client version outdated, please update',
'523': 'client is online',
'524': 'client is flooding',
'525': 'client is modified',
'526': 'can not verify client at this moment',
'527': 'client is not permitted to log in',
'528': 'client is not subscribed to the channel',
'768': 'invalid channelID',
'769': 'max channels protocol limit reached',
'770': 'already member of channel',
'771': 'channel name is already in use',
'772': 'channel not empty',
'773': 'can not delete default channel',
'774': 'default channel requires permanent',
'775': 'invalid channel flags',
'776': 'permanent channel can not be child of non permanent channel',
'777': 'channel maxclient reached',
'778': 'channel maxfamily reached',
'779': 'invalid channel order',
'780': 'channel does not support filetransfers',
'781': 'invalid channel password',
'782': 'channel is private channel',
'783': 'invalid security hash supplied by client',
'1024': 'invalid serverID',
'1025': 'server is running',
'1026': 'server is shutting down',
'1027': 'server maxclient reached',
'1028': 'invalid server password',
'1029': 'deployment active',
'1030': 'unable to stop own server in your connection class',
'1031': 'server is virtual',
'1032': 'server wrong machineID',
'1033': 'server is not running',
'1034': 'server is booting up',
'1035': 'server got an invalid status for this operation',
'1036': 'server modal quit',
'1037': 'server version is too old for command',
'1280': 'database error',
'1281': 'database empty result set',
'1282': 'database duplicate entry',
'1283': 'database no modifications',
'1284': 'database invalid constraint',
'1285': 'database reinvoke command',
'1536': 'invalid quote',
'1537': 'invalid parameter count',
'1538': 'invalid parameter',
'1539': 'parameter not found',
'1540': 'convert error',
'1541': 'invalid parameter size',
'1542': 'missing required parameter',
'1543': 'invalid checksum',
'1792': 'virtual server got a critical error',
'1793': 'Connection lost',
'1794': 'not connected',
'1795': 'no cached connection info',
'1796': 'currently not possible',
'1797': 'failed connection initialization',
'1798': 'could not resolve hostname',
'1799': 'invalid server connection handler ID',
'1800': 'could not initialize Input Manager',
'1801': 'client library not initialized',
'1802': 'server library not initialized',
'1803': 'too many whisper targets',
'1804': 'no whisper targets found',
'2048': 'invalid file name',
'2049': 'invalid file permissions',
'2050': 'file already exists',
'2051': 'file not found',
'2052': 'file input/output error',
'2053': 'invalid file transfer ID',
'2054': 'invalid file path',
'2055': 'no files available',
'2056': 'overwrite excludes resume',
'2057': 'invalid file size',
'2058': 'file already in use',
'2059': 'could not open file transfer connection',
'2060': 'no space left on device (disk full?)',
'2061': "file exceeds file system's maximum file size",
'2062': 'file transfer connection timeout',
'2063': 'lost file transfer connection',
'2064': 'file exceeds supplied file size',
'2065': 'file transfer complete',
'2066': 'file transfer canceled',
'2067': 'file transfer interrupted',
'2068': 'file transfer server quota exceeded',
'2069': 'file transfer client quota exceeded',
'2070': 'file transfer reset',
'2071': 'file transfer limit reached',
'2304': 'preprocessor disabled',
'2305': 'internal preprocessor',
'2306': 'internal encoder',
'2307': 'internal playback',
'2308': 'no capture device available',
'2309': 'no playback device available',
'2310': 'could not open capture device',
'2311': 'could not open playback device',
'2312': 'ServerConnectionHandler has a device registered',
'2313': 'invalid capture device',
'2314': 'invalid clayback device',
'2315': 'invalid wave file',
'2316': 'wave file type not supported',
'2317': 'could not open wave file',
'2318': 'internal capture',
'2319': 'device still in use',
'2320': 'device already registerred',
'2321': 'device not registered/known',
'2322': 'unsupported frequency',
'2323': 'invalid channel count',
'2324': 'read error in wave',
'2325': 'sound need more data',
'2326': 'sound device was busy',
'2327': 'there is no sound data for this period',
'2328': 'Channelmask set bits count (speakers) is not the same as channel (count)',
'2560': 'invalid group ID',
'2561': 'duplicate entry',
'2562': 'invalid permission ID',
'2563': 'empty result set',
'2564': 'access to default group is forbidden',
'2565': 'invalid size',
'2566': 'invalid value',
'2567': 'group is not empty',
'2568': 'insufficient client permissions',
'2569': 'insufficient group modify power',
'2570': 'insufficient permission modify power',
'2571': 'template group is currently used',
'2572': 'permission error',
'2816': 'virtualserver limit reached',
'2817': 'max slot limit reached',
'2818': 'license file not found',
'2819': 'license date not ok',
'2820': 'unable to connect to accounting server',
'2821': 'unknown accounting error',
'2822': 'accounting server error',
'2823': 'instance limit reached',
'2824': 'instance check error',
'2825': 'license file invalid',
'2826': 'virtualserver is running elsewhere',
'2827': 'virtualserver running in same instance already',
'2828': 'virtualserver already started',
'2829': 'virtualserver not started',
'2830': '',
'3072': 'invalid message id',
'3328': 'invalid ban id',
'3329': 'connection failed, you are banned',
'3330': 'rename failed, new name is banned',
'3331': 'flood ban',
'3584': 'unable to initialize tts',
'3840': 'invalid privilege key',
'4096': '',
'4097': '',
'4098': '',
'4099': '',
'4100': '',
'4101': '',
'4102': '',
'4103': '',
'4352': 'invalid password',
'4353': 'invalid request',
'4354': 'no (more) slots available',
'4355': 'pool missing',
'4356': 'pool unknown',
'4357': 'unknown ip location (perhaps LAN ip?)',
'4358': 'internal error (tried exceeded)',
'4359': 'too many slots requested',
'4360': 'too many reserved',
'4361': 'could not connect to provisioning server',
'4368': 'authentication server not connected',
'4369': 'authentication data too large',
'4370': 'already initialized',
'4371': 'not initialized',
'4372': 'already connecting',
'4373': 'already connected',
'4374': '',
'4375': 'io_error',
'4376': '',
'4377': '',
'4378': '',
}

View File

@@ -1,139 +0,0 @@
from __future__ import unicode_literals
import os
import requests
import json
from django.conf import settings
import logging
logger = logging.getLogger(__name__)
class XenForoManager:
def __init__(self):
if not settings.XENFORO_ENDPOINT:
logger.debug("Could not find XenForo endpoint")
if not settings.XENFORO_APIKEY:
logger.debug("XenForo API Key not found")
pass
@staticmethod
def __sanitize_username(username):
sanitized = username.replace(" ", "_")
return sanitized
@staticmethod
def __generate_password():
return os.urandom(8).encode('hex')
@staticmethod
def exec_http_request(http_params):
default_params = {
'hash': settings.XENFORO_APIKEY
}
http_params.update(default_params)
r = requests.get(settings.XENFORO_ENDPOINT, params=http_params)
return r
@staticmethod
def add_user(username, email):
sanitized = XenForoManager.__sanitize_username(username)
password = XenForoManager.__generate_password()
data = {
'action': 'register',
'username': sanitized,
'password': password,
'email': email,
'group': settings.XENFORO_DEFAULT_GROUP,
'visible': '1',
'user_state': 'valid'
}
r = XenForoManager.exec_http_request(data)
# check if the user already exist but was disabled
if r.status_code != 200:
if json.loads(r.text)['error'] == 7:
data = XenForoManager.reactivate_user(sanitized)
return data
response = {
'response': {
'message': r.text,
'status_code': r.status_code
}
}
data.update(response)
return data
@staticmethod
def reset_password(username):
password = XenForoManager.__generate_password()
data = {
'action': 'editUser',
'user': username,
'password': password
}
r = XenForoManager.exec_http_request(data)
response = {
'response': {
'message': r.text,
'status_code': r.status_code
}
}
data.update(response)
return data
@staticmethod
def disable_user(username):
data = {
'action': 'editUser',
'user': username,
'remove_groups': settings.XENFORO_DEFAULT_GROUP
}
r = XenForoManager.exec_http_request(data)
return r
@staticmethod
def reactivate_user(username):
data = {
'action': 'editUser',
'user': username,
'add_groups': settings.XENFORO_DEFAULT_GROUP,
'password': XenForoManager.__generate_password()
}
r = XenForoManager.exec_http_request(data)
response = {
'response': {
'message': r.text,
'status_code': r.status_code
},
'username': username
}
data.update(response)
return data
@staticmethod
def update_user_password(username, raw_password):
data = {
'action': 'editUser',
'user': username,
'password': raw_password
}
r = XenForoManager.exec_http_request(data)
response = {
'response': {
'message': r.text,
'status_code': r.status_code
},
'username': username
}
data.update(response)
return data