Adarnof's Little Things (#547)

* Port to Django 1.10
Initial migrations for current states of all models. Requires faking to retain data.
Removed all references to render_to_response, replacing with render shortcut.
Same for HttpResponseRedirect to render shortcut.
Corrected notification signal import to wait for app registry to finish loading.

* Correct typos from render conversion

* Modify models to suppress Django field warnings

* Script for automatic database conversion
 - fakes initial migrations to preserve data
Include LOGIN_URL setting

* Correct context processor import typo

* Removed pathfinder support.
Current pathfinder versions require SSO, not APIs added to database.
Conditionally load additional database definitions only if services are enabled.
Prevents errors when running auth without creating all possible databases.

* Condense context processors

* Include Django 1.10 installation in migrate script
Remove syncdb/evolve, replace with migrate for update script

* Replaced member/blue perms with user state system
Removed sigtracker
Initial migrations for default perms and groups
Removed perm bootstrapping on first run

* Clean up services list

* Remove fleet fittings page

* Provide action feedback via django messaging
Display unread notification count
Correct left navbar alignment

* Stop storing service passwords.
Provide them one time upon activation or reset.
Closes #177

* Add group sync buttons to admin site
Allow searcing of AuthServicesInfo models
Display user main character

* Correct button CSS to remove underlines on hover

* Added bulk actions to notifications
Altered notification default ordering

* Centralize API key validation.
Remove unused error count on API key model.
Restructure API key refresh task to queue all keys per user and await completion.
Closes #350

* Example configuration files for supervisor.
Copy to /etc/supervisor/conf.d and restart to take effect.
Closes #521
Closes #266

* Pre-save receiver for member/blue state switching
Removed is_blue field
Added link to admin site

* Remove all hardcoded URLs from views and templates
Correct missing render arguments
Closes #540

* Correct celeryd process directory

* Migration to automatically set user states.
Runs instead of waiting for next API refresh cycle. Should make the transition much easier.

* Verify service accounts accessible to member state

* Restructure project to remove unnecessary apps.
(celerytask, util, portal, registraion apps)
Added workarounds for python 3 compatibility.

* Correct python2 compatibility

* Check services against state being changed to

* Python3 compatibility fixes

* Relocate x2bool py3 fix

* SSO integration for logging in to existing accounts.

* Add missing url names for fleetup reverse

* Sanitize groupnames before syncing.

* Correct trailing slash preventing url resolution

* Alter group name sanitization to allow periods and hyphens

* Correct state check on pre_save model for corp/alliance group assignment

* Remove sigtracker table from old dbs to allow user deletion

* Include missing celery configuration

* Teamspeak error handling

* Prevent celery worker deadlock on async group result wait

* Correct active navbar links for translated urls.
Correct corp status url resolution for some links.
Remove DiscordAuthToken model.
This commit is contained in:
Adarnof
2016-10-16 18:01:14 -04:00
committed by GitHub
parent 56136d050a
commit 1b4f5e4e88
220 changed files with 5716 additions and 5331 deletions

View File

@@ -0,0 +1,2 @@
from __future__ import unicode_literals
default_app_config = 'services.apps.ServicesConfig'

View File

@@ -1,13 +1,15 @@
from __future__ import unicode_literals
from django.contrib import admin
from .models import AuthTS
from .models import DiscordAuthToken
from .models import MumbleUser
from .models import GroupCache
from services.models import AuthTS
from services.models import MumbleUser
from services.models import GroupCache
class AuthTSgroupAdmin(admin.ModelAdmin):
fields = ['auth_group','ts_group']
fields = ['auth_group', 'ts_group']
filter_horizontal = ('ts_group',)
admin.site.register(AuthTS, AuthTSgroupAdmin)
admin.site.register(MumbleUser)

10
services/apps.py Normal file
View File

@@ -0,0 +1,10 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class ServicesConfig(AppConfig):
name = 'services'
def ready(self):
import services.signals

View File

@@ -0,0 +1,31 @@
from __future__ import unicode_literals
from django.conf import settings
from django.utils import timezone
def auth_settings(request):
return {
'DOMAIN': settings.DOMAIN,
'MUMBLE_URL': settings.MUMBLE_URL,
'FORUM_URL': settings.FORUM_URL,
'TEAMSPEAK3_PUBLIC_URL': settings.TEAMSPEAK3_PUBLIC_URL,
'JACK_KNIFE_URL': settings.JACK_KNIFE_URL,
'DISCORD_SERVER_ID': settings.DISCORD_GUILD_ID,
'KILLBOARD_URL': settings.KILLBOARD_URL,
'DISCOURSE_URL': settings.DISCOURSE_URL,
'IPS4_URL': settings.IPS4_URL,
'SMF_URL': settings.SMF_URL,
'MARKET_URL': settings.MARKET_URL,
'EXTERNAL_MEDIA_URL': settings.EXTERNAL_MEDIA_URL,
'CURRENT_UTC_TIME': timezone.now(),
'BLUE_API_MASK': settings.BLUE_API_MASK,
'BLUE_API_ACCOUNT': settings.BLUE_API_ACCOUNT,
'MEMBER_API_MASK': settings.MEMBER_API_MASK,
'MEMBER_API_ACCOUNT': settings.MEMBER_API_ACCOUNT,
'JABBER_URL': settings.JABBER_URL,
'ALLIANCE_NAME': settings.ALLIANCE_NAME,
'ALLIANCE_ID': settings.ALLIANCE_ID,
'CORP_NAME': settings.CORP_NAME,
'CORP_ID': settings.CORP_ID,
'IS_CORP': settings.IS_CORP,
}

View File

@@ -1,7 +1,9 @@
from __future__ import unicode_literals
from django import forms
from services.managers.teamspeak3_manager import Teamspeak3Manager
from django.utils.translation import ugettext_lazy as _
class JabberBroadcastForm(forms.Form):
group = forms.ChoiceField(label=_('Group'), widget=forms.Select)
message = forms.CharField(label=_('Message'), widget=forms.Textarea)
@@ -17,23 +19,29 @@ class FleetFormatterForm(forms.Form):
formup_time = forms.CharField(label=_('Formup Time:'), required=True)
expected_duration = forms.CharField(label=_('Expected Duration:'), required=True)
purpose = forms.CharField(label=_('Purpose:'), required=True)
reimbursable = forms.ChoiceField(label=_('Reimbursable?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))], required=True)
important = forms.ChoiceField(label=_('Important?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))], required=True)
reimbursable = forms.ChoiceField(label=_('Reimbursable?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))],
required=True)
important = forms.ChoiceField(label=_('Important?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))],
required=True)
comments = forms.CharField(label=_('Comments'), widget=forms.Textarea, required=False)
class DiscordForm(forms.Form):
email = forms.CharField(label=_("Email Address"), required=True)
password = forms.CharField(label=_("Password"), required=True, widget=forms.PasswordInput)
update_avatar = forms.BooleanField(label=_("Update Avatar"), required=False, initial=True)
class ServicePasswordForm(forms.Form):
password = forms.CharField(label=_("Password"), required=True)
def clean_password(self):
password = self.cleaned_data['password']
if not len(password) >= 8:
raise forms.ValidationError(_("Password must be at least 8 characters long."))
return password
class TeamspeakJoinForm(forms.Form):
username = forms.CharField(widget=forms.HiddenInput())

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -1,11 +1,9 @@
from __future__ import unicode_literals
import requests
import json
from django.conf import settings
import re
import os
import urllib
import base64
from services.models import DiscordAuthToken, GroupCache
from django.conf import settings
from services.models import GroupCache
from requests_oauthlib import OAuth2Session
import logging
import datetime
@@ -16,442 +14,10 @@ logger = logging.getLogger(__name__)
DISCORD_URL = "https://discordapp.com/api"
EVE_IMAGE_SERVER = "https://image.eveonline.com"
class DiscordAPIManager:
def __init__(self, server_id, email, password, user=None):
self.token = DiscordAPIManager.get_token_by_user(email, password, user)
self.email = email
self.password = password
self.server_id = server_id
logger.debug("Initialized DiscordAPIManager with server id %s" % self.server_id)
@staticmethod
def validate_token(token):
custom_headers = {'accept': 'application/json', 'authorization': token}
path = DISCORD_URL + "/users/@me"
r = requests.get(path, headers=custom_headers)
if r.status_code == 200:
logger.debug("Token starting with %s passed validation." % token[0:5])
return True
else:
logger.debug("Token starting with %s failed validation with status code %s" % (token[0:5], r.status_code))
return False
@staticmethod
def get_auth_token():
data = {
"email" : settings.DISCORD_USER_EMAIL,
"password": settings.DISCORD_USER_PASSWORD,
}
custom_headers = {'content-type':'application/json'}
path = DISCORD_URL + "/auth/login"
r = requests.post(path, headers=custom_headers, data=json.dumps(data))
logger.debug("Received status code %s during token generation for settings discord user." % r.status_code)
r.raise_for_status()
return r.json()['token']
def add_server(self, name):
data = {"name": name}
custom_headers = {'content-type':'application/json', 'authorization': self.token}
path = DISCORD_URL + "/guilds"
r = requests.post(path, headers=custom_headers, data=json.dumps(data))
r.raise_for_status()
return r.json()
def rename_server(self, name):
data = {"name": name}
custom_headers = {'content-type':'application/json', 'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id)
r = requests.patch(path, headers=custom_headers, data=json.dumps(data))
r.raise_for_status()
return r.json()
def delete_server(self):
custom_headers = {'content-type':'application/json', 'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id)
r = requests.delete(path, headers=custom_headers)
r.raise_for_status()
def get_members(self):
custom_headers = {'accept':'application/json', 'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members"
r = requests.get(path, headers=custom_headers)
r.raise_for_status()
return r.json()
def get_bans(self):
custom_headers = {'accept':'application/json', 'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/bans"
r = requests.get(path, headers=custom_headers)
r.raise_for_status()
return r.json()
def ban_user(self, user_id, delete_message_age=0):
custom_headers = {'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/bans/" + str(user_id) + "?delete-message-days=" + str(delete_message_age)
r = requests.put(path, headers=custom_headers)
logger.debug("Received status code %s after banning user %s" % (r.status_code, user_id))
r.raise_for_status()
def unban_user(self, user_id):
custom_headers = {'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/bans/" + str(user_id)
r = requests.delete(path, headers=custom_headers)
logger.debug("Received status code %s after deleting ban for user %s" % (r.status_code, user_id))
r.raise_for_status()
def generate_role(self):
custom_headers = {'accept':'application/json', 'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_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()
def edit_role(self, role_id, name, color=0, hoist=True, permissions=36785152):
custom_headers = {'content-type':'application/json', 'authorization': self.token}
data = {
'color': color,
'hoist': hoist,
'name': name,
'permissions': permissions,
}
path = DISCORD_URL + "/guilds/" + str(self.server_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()
def delete_role(self, role_id):
custom_headers = {'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/roles/" + str(role_id)
r = requests.delete(path, headers=custom_headers)
r.raise_for_status()
@staticmethod
def get_invite(invite_id):
custom_headers = {'accept': 'application/json'}
path = DISCORD_URL + "/invite/" + str(invite_id)
r = requests.get(path, headers=custom_headers)
r.raise_for_status()
return r.json()
def accept_invite(self, invite_id):
custom_headers = {'accept': 'application/json', 'authorization': self.token}
path = DISCORD_URL + "/invite/" + str(invite_id)
r = requests.post(path, headers=custom_headers)
logger.debug("Received status code %s after accepting invite." % r.status_code)
r.raise_for_status()
return r.json()
def create_invite(self, max_age=600, max_uses=1, temporary=True, xkcdpass=False):
custom_headers = {'authorization': self.token}
path = DISCORD_URL + "/channels/" + str(self.server_id) + "/invites"
data = {
'max_age': max_age,
'max_uses': max_uses,
'temporary': temporary,
'xkcdpass': xkcdpass,
}
r = requests.post(path, headers=custom_headers, data=json.dumps(data))
logger.debug("Received status code %s after creating invite." % r.status_code)
r.raise_for_status()
return r.json()
def delete_invite(self, invite_id):
custom_headers = {'authorization': self.token}
path = DISCORD_URL + "/invite/" + str(invite_id)
r = requests.delete(path, headers=custom_headers)
r.raise_for_status()
def set_roles(self, user_id, role_ids):
custom_headers = {'authorization': self.token, 'content-type':'application/json'}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members/" + str(user_id)
data = { 'roles': role_ids }
r = requests.patch(path, headers=custom_headers, data=json.dumps(data))
logger.debug("Received status code %s after setting roles of user %s to %s" % (r.status_code, user_id, role_ids))
r.raise_for_status()
@staticmethod
def register_user(server_id, username, invite_code, password, email):
custom_headers = {'content-type': 'application/json'}
data = {
'fingerprint': None,
'username': username,
'invite': invite_code,
'password': password,
'email': email,
}
path = DISCORD_URL + "/auth/register"
r = requests.post(path, headers=custom_headers, data=json.dumps(data))
r.raise_for_status()
def kick_user(self, user_id):
custom_headers = {'authorization': self.token}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members/" + str(user_id)
r = requests.delete(path, headers=custom_headers)
r.raise_for_status()
def get_members(self):
custom_headers = {'authorization': self.token, 'accept':'application/json'}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members"
r = requests.get(path, headers=custom_headers)
r.raise_for_status()
return r.json()
def get_user_id(self, username):
all_members = self.get_members()
for member in all_members:
if member['user']['username'] == username:
return member['user']['id']
raise KeyError('User not found on server: ' + username)
def get_roles(self):
custom_headers = {'authorization': self.token, 'accept':'application/json'}
path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/roles"
r = requests.get(path, headers=custom_headers)
logger.debug("Received status code %s after retrieving role list from server." % r.status_code)
r.raise_for_status()
return r.json()
def get_group_id(self, group_name):
logger.debug("Determining role id for group name %s" % group_name)
all_roles = self.get_roles()
logger.debug("Retrieved role list for server: %s" % all_roles)
for role in all_roles:
logger.debug("Checking role %s" % role)
if role['name'] == group_name:
logger.debug("Found role matching name: %s" % role['id'])
return role['id']
logger.debug("Role not found on server. Raising KeyError")
raise KeyError('Group not found on server: ' + group_name)
@staticmethod
def get_token_by_user(email, password, user):
if DiscordAuthToken.objects.filter(email=email).exists():
auth = DiscordAuthToken.objects.get(email=email)
if not auth.user == user:
raise ValueError("User mismatch while validating DiscordAuthToken for email %s - user %s, requesting user %s" % (email, auth.user, user))
logger.debug("Discord auth token cached for supplied email starting with %s" % email[0:3])
auth = DiscordAuthToken.objects.get(email=email, user=user)
if DiscordAPIManager.validate_token(auth.token):
logger.debug("Token still valid. Returning token starting with %s" % auth.token[0:5])
return auth.token
else:
logger.debug("Token has expired. Deleting.")
auth.delete()
logger.debug("Generating auth token for email starting with %s user %s and password of length %s" % (email[0:3], user, len(password)))
data = {
"email" : email,
"password": password,
}
custom_headers = {'content-type':'application/json'}
path = DISCORD_URL + "/auth/login"
r = requests.post(path, headers=custom_headers, data=json.dumps(data))
logger.debug("Received status code %s after generating auth token for custom user." % r.status_code)
r.raise_for_status()
token = r.json()['token']
auth = DiscordAuthToken(email=email, token=token, user=user)
auth.save()
logger.debug("Created cached token for email starting with %s" % email[0:3])
return token
def get_profile(self):
custom_headers = {'accept': 'application/json', 'authorization': self.token}
path = DISCORD_URL + "/users/@me"
r = requests.get(path, headers=custom_headers)
logger.debug("Received status code %s after retrieving user profile with email %s" % (r.status_code, self.email[0:3]))
r.raise_for_status()
return r.json()
@staticmethod
def get_user_profile(email, password, user):
token = DiscordAPIManager.get_token_by_user(email, password, user)
custom_headers = {'accept': 'application/json', 'authorization': token}
path = DISCORD_URL + "/users/@me"
r = requests.get(path, headers=custom_headers)
logger.debug("Received status code %s after retrieving user profile with email %s" % (r.status_code, email[0:3]))
r.raise_for_status()
return r.json()
@staticmethod
def set_user_password(email, current_password, new_password, user):
profile = DiscordAPIManager.get_user_profile(email, current_password, user)
avatar = profile['avatar']
username = profile['username']
data = {
'avatar': avatar,
'username': username,
'password': current_password,
'new_password': new_password,
'email': email,
}
path = DISCORD_URL + "/users/@me"
custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_token_by_user(email, current_password)}
r = requests.patch(path, headers=custom_headers, data=json.dumps(data))
r.raise_for_status()
return r.json()
@staticmethod
def set_user_avatar(email, current_password, user, avatar_url):
profile = DiscordAPIManager.get_user_profile(email, current_password, user)
avatar = "data:image/jpeg;base64," + base64.b64encode(urllib.urlopen(avatar_url).read())
username = profile['username']
data = {
'avatar': avatar,
'username': username,
'password': current_password,
'email': email
}
path = DISCORD_URL + "/users/@me"
custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_token_by_user(email, current_password, user)}
r = requests.patch(path, headers=custom_headers, data=json.dumps(data))
r.raise_for_status()
return r.json()
@staticmethod
def destroy_user(email, current_password):
data = {
'avatar': None,
'username': os.urandom(8).encode('hex'),
'password': current_password,
'email': os.urandom(8).encode('hex') + '@test.com',
}
path = DISCORD_URL + "/users/@me"
custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_token_by_user(email, current_password)}
r = requests.patch(path, headers=custom_headers, data=json.dumps(data))
r.raise_for_status
return r.json()
def check_if_user_banned(self, user_id):
bans = self.get_bans()
for b in bans:
if b['user']['id'] == str(user_id):
return True
return False
class DiscordManager:
def __init__(self):
pass
@staticmethod
def __sanatize_username(username):
clean = re.sub(r'[^\w]','_', username)
return clean
@staticmethod
def __generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def update_groups(user_id, groups):
logger.debug("Updating groups for user_id %s: %s" % (user_id, groups))
group_ids = []
api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD)
if len(groups) == 0:
logger.debug("No groups provided - generating empty array of group ids.")
group_ids = []
else:
for g in groups:
try:
logger.debug("Retrieving group id for group %s" % g)
group_id = api.get_group_id(g)
group_ids.append(group_id)
logger.debug("Got id %s" % group_id)
except:
logger.debug("Group id retrieval generated exception - generating new group on discord server.", exc_info=True)
group_ids.append(DiscordManager.create_group(g))
logger.info("Setting discord groups for user %s to %s" % (user_id, group_ids))
api.set_roles(user_id, group_ids)
@staticmethod
def create_group(groupname):
logger.debug("Creating new group %s" % groupname)
api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD)
new_group = api.generate_role()
logger.debug("Created new role on server with id %s: %s" % (new_group['id'], new_group))
named_group = api.edit_role(new_group['id'], groupname)
logger.debug("Renamed group id %s to %s" % (new_group['id'], groupname))
logger.info("Created new group on discord server with name %s" % groupname)
return named_group['id']
@staticmethod
def lock_user(user_id):
try:
api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD)
api.ban_user(user_id)
return True
except:
return False
@staticmethod
def unlock_user(user_id):
try:
api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD)
api.unban_user(user_id)
return True
except:
return False
@staticmethod
def update_user_password(email, current_password, user):
new_password = DiscordManager.__generate_random_pass()
try:
profile = DiscordAPIManager.set_user_password(email, current_password, new_password, user)
return new_password
except:
return current_password
@staticmethod
def update_user_avatar(email, password, user, char_id):
try:
char_url = EVE_IMAGE_SERVER + "/character/" + str(char_id) + "_256.jpg"
logger.debug("Character image URL for %s: %s" % (user, char_url))
DiscordAPIManager.set_user_avatar(email, password, user, char_url)
return True
except:
return False
@staticmethod
def add_user(email, password, user):
try:
logger.debug("Adding new user %s to discord with email %s and password of length %s" % (user, email[0:3], len(password)))
server_api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD)
user_api = DiscordAPIManager(settings.DISCORD_SERVER_ID, email, password, user=user)
profile = user_api.get_profile()
logger.debug("Got profile for user: %s" % profile)
user_id = profile['id']
logger.debug("Determined user id: %s" % user_id)
if server_api.check_if_user_banned(user_id):
logger.debug("User is currently banned. Unbanning %s" % user_id)
server_api.unban_user(user_id)
invite_code = server_api.create_invite()['code']
logger.debug("Generated invite code beginning with %s" % invite_code[0:5])
user_api.accept_invite(invite_code)
logger.info("Added user to discord server %s with id %s" % (settings.DISCORD_SERVER_ID, user_id))
return user_id
except:
logger.exception("An unhandled exception has occured.")
return ""
@staticmethod
def delete_user(user_id):
try:
logger.debug("Deleting user with id %s from discord server." % user_id)
api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD)
DiscordManager.update_groups(user_id, [])
api.ban_user(user_id)
logger.info("Deleted user with id %s from discord server id %s" % (user_id, settings.DISCORD_SERVER_ID))
return True
except:
logger.exception("An unhandled exception has occured.")
return False
AUTH_URL = "https://discordapp.com/api/oauth2/authorize"
TOKEN_URL = "https://discordapp.com/api/oauth2/token"
# kick, manage roles
# kick, manage roles, manage nicknames
BOT_PERMISSIONS = 0x00000002 + 0x10000000 + 0x08000000
# get user ID, accept invite
@@ -462,7 +28,16 @@ SCOPES = [
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)
@@ -506,11 +81,12 @@ class DiscordOAuthManager:
@staticmethod
def update_nickname(user_id, nickname):
try:
custom_headers = {'content-type':'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
data = { 'nick': nickname, }
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))
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
@@ -584,7 +160,7 @@ class DiscordOAuthManager:
@staticmethod
def __generate_role():
custom_headers = {'accept':'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
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)
@@ -593,11 +169,11 @@ class DiscordOAuthManager:
@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}
custom_headers = {'content-type': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN}
data = {
'color': color,
'hoist': hoist,
'name': name,
'name': name,
'permissions': permissions,
}
path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/roles/" + str(role_id)
@@ -609,13 +185,13 @@ class DiscordOAuthManager:
@staticmethod
def __create_group(name):
role = DiscordOAuthManager.__generate_role()
new_role = DiscordOAuthManager.__edit_role(role['id'], name)
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(g) for g in 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)

View File

@@ -1,8 +1,10 @@
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
@@ -113,7 +115,11 @@ ENDPOINTS = {
},
}
class DiscourseManager:
def __init__(self):
pass
GROUP_CACHE_MAX_AGE = datetime.timedelta(minutes=30)
REVOKED_EMAIL = 'revoked@' + settings.DOMAIN
SUSPEND_DAYS = 99999
@@ -136,7 +142,7 @@ class DiscourseManager:
if arg in kwargs:
data[arg] = kwargs[arg]
for arg in kwargs:
if not arg in endpoint['args']['required'] and not arg in endpoint['args']['optional']:
if arg not in endpoint['args']['required'] and arg not in endpoint['args']['optional']:
logger.warn("Received unrecognized kwarg %s for endpoint %s" % (arg, endpoint))
r = endpoint['method'](settings.DISCOURSE_URL + path, params=params, json=data)
out = r.text
@@ -218,10 +224,10 @@ class DiscourseManager:
@staticmethod
def __generate_group_dict(names):
dict = {}
group_dict = {}
for name in names:
dict[name] = DiscourseManager.__group_name_to_id(name)
return dict
group_dict[name] = DiscourseManager.__group_name_to_id(name)
return group_dict
@staticmethod
def __get_user_groups(username):
@@ -271,7 +277,8 @@ class DiscourseManager:
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)
return DiscourseManager.__exc(endpoint, id, duration=DiscourseManager.SUSPEND_DAYS,
reason=DiscourseManager.SUSPEND_REASON)
@staticmethod
def __unsuspend(username):
@@ -287,9 +294,15 @@ class DiscourseManager:
@staticmethod
def _sanatize_username(username):
sanatized = username.replace(" ", "_")
sanatized = sanatized.strip(' _')
sanatized = sanatized.replace("'", "")
return sanatized
@staticmethod
def _sanitize_groupname(name):
name = name.strip(' _')
return re.sub('[^\w]', '', name)
@staticmethod
def add_user(username, email):
logger.debug("Adding new discourse user %s" % username)
@@ -306,7 +319,7 @@ class DiscourseManager:
return safe_username, password
except:
logger.exception("Failed to add new discourse user %s" % username)
return "",""
return "", ""
@staticmethod
def delete_user(username):
@@ -323,15 +336,16 @@ class DiscourseManager:
def update_groups(username, raw_groups):
groups = []
for g in raw_groups:
groups.append(g[:20])
groups.append(DiscourseManager._sanitize_groupname(g[:20]))
logger.debug("Updating discourse user %s groups to %s" % (username, groups))
group_dict = DiscourseManager.__generate_group_dict(groups)
inv_group_dict = {v:k for k,v in group_dict.items()}
inv_group_dict = {v: k for k, v in group_dict.items()}
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 inv_group_dict[x] in groups]
if add_groups or rem_groups:
logger.info("Updating discourse user %s groups: adding %s, removing %s" % (username, add_groups, 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:

View File

@@ -1,20 +1,48 @@
from __future__ import unicode_literals
import evelink.api
import evelink.char
import evelink.eve
from authentication.states import MEMBER_STATE, BLUE_STATE
from authentication.models import AuthServicesInfo
from eveonline.models import EveCharacter
from django.conf import settings
import logging
logger = logging.getLogger(__name__)
class EveApiManager():
class EveApiManager:
def __init__(self):
pass
class ApiValidationError(Exception):
def __init__(self, msg, api_id):
self.msg = msg
self.api_id = api_id
def __str__(self):
return self.msg
class ApiMaskValidationError(ApiValidationError):
def __init__(self, required_mask, api_mask, api_id):
msg = 'Insufficient API mask provided. Required: %s Got: %s' % (required_mask, api_mask)
self.required_mask = required_mask
self.api_mask = api_mask
super(EveApiManager.ApiMaskValidationError, self).__init__(msg, api_id)
class ApiAccountValidationError(ApiValidationError):
def __init__(self, api_id):
msg = 'Insufficient API access provided. Full account access is required, got character restricted.'
super(EveApiManager.ApiAccountValidationError, self).__init__(msg, api_id)
class ApiInvalidError(ApiValidationError):
def __init__(self, api_id):
msg = 'Key is invalid.'
super(EveApiManager.ApiInvalidError, self).__init__(msg, api_id)
@staticmethod
def get_characters_from_api(api_id, api_key):
chars = []
logger.debug("Getting characters from api id %s" % api_id)
api = evelink.api.API(api_key=(api_id, api_key))
# Should get characters
@@ -26,7 +54,6 @@ class EveApiManager():
@staticmethod
def get_corporation_ticker_from_id(corp_id):
logger.debug("Getting ticker for corp id %s" % corp_id)
ticker = ""
api = evelink.api.API()
corp = evelink.corp.Corp(api)
response = corp.corporation_sheet(corp_id)
@@ -37,7 +64,6 @@ class EveApiManager():
@staticmethod
def get_alliance_information(alliance_id):
results = {}
logger.debug("Getting info for alliance with id %s" % alliance_id)
api = evelink.api.API()
eve = evelink.eve.EVE(api=api)
@@ -49,7 +75,6 @@ class EveApiManager():
@staticmethod
def get_corporation_information(corp_id):
logger.debug("Getting info for corp with id %s" % corp_id)
results = {}
api = evelink.api.API()
corp = evelink.corp.Corp(api=api)
corpinfo = corp.corporation_sheet(corp_id=int(corp_id))
@@ -57,6 +82,12 @@ class EveApiManager():
logger.debug("Got corp info %s" % results)
return results
@staticmethod
def get_api_info(api_id, api_key):
api = evelink.api.API(api_key=(api_id, api_key))
account = evelink.account.Account(api=api)
return account.key_info()[0]
@staticmethod
def check_api_is_type_account(api_id, api_key):
logger.debug("Checking if api id %s is account." % api_id)
@@ -83,7 +114,7 @@ class EveApiManager():
info = account.key_info()
logger.debug("API has mask %s, required is %s" % (info[0]['access_mask'], settings.BLUE_API_MASK))
return info[0]['access_mask'] & int(settings.BLUE_API_MASK) == int(settings.BLUE_API_MASK)
@staticmethod
def get_api_info(api_id, api_key):
logger.debug("Getting api info for key id %s" % api_id)
@@ -98,7 +129,7 @@ class EveApiManager():
logger.debug("Checking if api id %s is valid." % api_id)
api = evelink.api.API(api_key=(api_id, api_key))
account = evelink.account.Account(api=api)
info = account.key_info()
account.key_info()
logger.info("Verified api id %s is still valid." % api_id)
return True
@@ -108,10 +139,10 @@ class EveApiManager():
try:
api = evelink.api.API()
server = evelink.server.Server(api=api)
info = server.server_status()
server.server_status()
logger.info("Verified API server is online and reachable.")
return True
except evelink.api.APIError as error:
except evelink.api.APIError:
logger.exception("APIError occured while trying to query api server. Possibly offline?")
logger.warn("Unable to reach API server.")
@@ -124,7 +155,7 @@ class EveApiManager():
api = evelink.api.API()
corp = evelink.corp.Corp(api=api)
corpinfo = corp.corporation_sheet(corp_id=int(corp_id))
results = corpinfo[0]
assert corpinfo[0]
logger.debug("Confirmed id %s is a corp." % corp_id)
return True
except evelink.api.APIError as error:
@@ -160,11 +191,10 @@ class EveApiManager():
results = membertracking.result
logger.debug("Got corp membertracking from settings: %s" % results)
return results
except evelink.api.APIError as error:
except evelink.api.APIError:
logger.exception("Unhandled APIError occured.")
return {}
@staticmethod
def check_if_id_is_alliance(alliance_id):
logger.debug("Checking if id %s is an alliance." % alliance_id)
@@ -176,8 +206,9 @@ class EveApiManager():
if results:
logger.debug("Confirmed id %s is an alliance." % alliance_id)
return True
except evelink.api.APIError as error:
logger.exception("APIError occured while checking if id %s is an alliance. Possibly not alliance?" % alliance_id)
except evelink.api.APIError:
logger.exception(
"APIError occured while checking if id %s is an alliance. Possibly not alliance?" % alliance_id)
except KeyError:
logger.debug("Alliance with id %s not found in active alliance list." % alliance_id)
return False
@@ -194,8 +225,10 @@ class EveApiManager():
if results:
logger.debug("Confirmed id %s is a character." % character_id)
return True
except evelink.api.APIError as error:
logger.debug("APIError occured while checking if id %s is a character. Possibly not character?" % character_id, exc_info=True)
except evelink.api.APIError:
logger.debug(
"APIError occured while checking if id %s is a character. Possibly not character?" % character_id,
exc_info=True)
logger.debug("Unable to verify id %s is a character." % character_id)
return False
@@ -213,15 +246,16 @@ class EveApiManager():
else:
logger.debug("Verified alliance id %s does not exist." % alliance_id)
return False
except evelink.api.APIError as error:
except evelink.api.APIError:
logger.exception("Unhandled APIError occured.")
return False
except ValueError as error:
#attempts to catch error resulting from checking alliance_of nonetype models
except ValueError:
# attempts to catch error resulting from checking alliance_of nonetype models
logger.exception("Unhandled ValueError occured. Possible nonetype alliance model.")
return False
logger.warn("Exception prevented verification of alliance id %s existance. Assuming false." % alliance_id)
return False
except:
logger.warn("Exception prevented verification of alliance id %s existance. Assuming false." % alliance_id)
return False
@staticmethod
def check_if_corp_exists(corp_id):
@@ -231,17 +265,20 @@ class EveApiManager():
corp = evelink.corp.Corp(api=api)
corpinfo = corp.corporation_sheet(corp_id=corp_id)
if corpinfo[0]['members']['current'] > 0:
logger.debug("Verified corp id %s exists with member count %s" % (corp_id, corpinfo[0]['members']['current']))
logger.debug(
"Verified corp id %s exists with member count %s" % (corp_id, corpinfo[0]['members']['current']))
return True
else:
logger.debug("Verified corp id %s has closed. Member count %s" % (corp_id, corpinfo[0]['members']['current']))
logger.debug(
"Verified corp id %s has closed. Member count %s" % (corp_id, corpinfo[0]['members']['current']))
return False
except evelink.api.APIError as error:
#could be smart and check for error code523 to verify error due to no corp instead of catch-all
except evelink.api.APIError:
# could be smart and check for error code523 to verify error due to no corp instead of catch-all
logger.exception("Unhandled APIError occured.")
return False
logger.warn("Exception prevented verification of corp id %s existance. Assuming false." % corp_id)
return False
except:
logger.warn("Exception prevented verification of corp id %s existance. Assuming false." % corp_id)
return False
@staticmethod
def validate_member_api(api_id, api_key):
@@ -249,7 +286,7 @@ class EveApiManager():
if EveApiManager.check_api_is_type_account(api_id, api_key) is False:
logger.info("Api id %s is not type account as required for members - failed validation." % api_id)
return False
if EveApiManager.check_api_is_full(api_id, api_key) is False:
logger.info("Api id %s does not meet member access mask requirements - failed validation." % api_id)
return False
@@ -265,3 +302,40 @@ class EveApiManager():
logger.info("Api id %s does not meet minimum blue access mask requirements - failed validation." % api_id)
return False
return True
@staticmethod
def validate_api(api_id, api_key, user):
try:
info = EveApiManager.get_api_info(api_id, api_key).result
chars = EveApiManager.get_characters_from_api(api_id, api_key).result
except evelink.api.APIError as e:
if int(e.code) in [221, 222]:
raise e
raise EveApiManager.ApiInvalidError(api_id)
except Exception:
raise EveApiManager.ApiInvalidError(api_id)
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
states = [auth.state]
from authentication.tasks import determine_membership_by_character # circular import issue
for char in chars:
evechar = EveCharacter()
evechar.character_name = chars[char]['name']
evechar.corporation_id = chars[char]['corp']['id']
evechar.alliance_id = chars[char]['alliance']['id']
states.append(determine_membership_by_character(evechar))
if MEMBER_STATE not in states and BLUE_STATE not in states:
# default to requiring member keys for applications
states.append(MEMBER_STATE)
logger.debug('Checking API %s for states %s' % (api_id, states))
for state in states:
if (state == MEMBER_STATE and settings.MEMBER_API_ACCOUNT) or (
state == BLUE_STATE and settings.BLUE_API_ACCOUNT):
if info['type'] != 'account':
raise EveApiManager.ApiAccountValidationError(api_id)
if state == MEMBER_STATE:
if int(info['access_mask']) & int(settings.MEMBER_API_MASK) != int(settings.MEMBER_API_MASK):
raise EveApiManager.ApiMaskValidationError(settings.MEMBER_API_MASK, info['access_mask'], api_id)
elif state == BLUE_STATE:
if int(info['access_mask']) & int(settings.BLUE_API_MASK) != int(settings.BLUE_API_MASK):
raise EveApiManager.ApiMaskValidationError(settings.BLUE_API_MASK, info['access_mask'], api_id)
return True

View File

@@ -1,13 +1,9 @@
from django.conf import settings
import logging
from __future__ import unicode_literals
import requests
#import requests_cache
import json
#requests_cache.install_cache("{}/evewho".format(settings.EVEWHO_CACHE_DIR), backend="sqlite", expire_after=3600)
class EveWhoManager():
class EveWhoManager:
def __init__(self):
pass
@@ -18,11 +14,11 @@ class EveWhoManager():
data = json.loads(jsondata.decode())
members = {}
page_count=0
page_count = 0
while len(data["characters"]):
for row in data["characters"]:
members[int(row["character_id"])] = {"name":row["name"], "id":int(row["character_id"])}
page_count=page_count+1
members[int(row["character_id"])] = {"name": row["name"], "id": int(row["character_id"])}
page_count += 1
jsondata = requests.get(url + "&page=%i" % page_count).content
data = json.loads(jsondata.decode())

View File

@@ -1,5 +1,5 @@
from __future__ import unicode_literals
from django.conf import settings
from django.http import HttpResponse
from datetime import datetime
import logging
@@ -13,43 +13,45 @@ userid = settings.FLEETUP_USER_ID
apiid = settings.FLEETUP_API_ID
groupid = settings.FLEETUP_GROUP_ID
class FleetUpManager():
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) + ""
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"]}
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):
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) + ""
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"]}
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):
@@ -58,18 +60,19 @@ class FleetUpManager():
@staticmethod
def get_fleetup_timers():
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Timers/" + str(groupid) + ""
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"]}
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):
@@ -78,45 +81,50 @@ class FleetUpManager():
@staticmethod
def get_fleetup_doctrines():
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Doctrines/" + str(groupid) + ""
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"]}
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":[]}
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
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}
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":{}}
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) + ""
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"]}
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):
@@ -125,25 +133,27 @@ class FleetUpManager():
@staticmethod
def get_fleetup_fitting(fittingnumber):
url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Fitting/%s" % 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"]}
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":{}}
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
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())
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?!")
@@ -155,13 +165,14 @@ class FleetUpManager():
@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
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"]}
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":{}}
return {"fitting_eft": {}}

View File

@@ -1,6 +1,13 @@
from __future__ import unicode_literals
import os
import xmlrpclib
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
@@ -8,6 +15,7 @@ import logging
logger = logging.getLogger(__name__)
class IPBoardManager:
def __init__(self):
pass
@@ -21,17 +29,21 @@ class IPBoardManager:
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 = xmlrpclib.Server(settings.IPBOARD_ENDPOINT, verbose=False)
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
print params
return getattr(server, func)(params)
except:
@@ -44,22 +56,22 @@ class IPBoardManager:
logger.debug("Adding user to IPBoard with username %s" % sanatized)
plain_password = IPBoardManager.__generate_random_pass()
password = md5(plain_password).hexdigest()
ret = IPBoardManager.exec_xmlrpc('createUser', username=sanatized, email=str(email), display_name=sanatized,
md5_passwordHash=password)
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 """
ret = IPBoardManager.exec_xmlrpc('deleteUser', username=username)
IPBoardManager.exec_xmlrpc('deleteUser', username=username)
logger.info("Deleted IPBoard user with username %s" % username)
return username
@staticmethod
def disable_user(username):
""" Disable user """
ret = IPBoardManager.exec_xmlrpc('disableUser', username=username)
IPBoardManager.exec_xmlrpc('disableUser', username=username)
logger.info("Disabled IPBoard user with username %s" % username)
return username
@@ -67,8 +79,9 @@ class IPBoardManager:
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]))
ret = IPBoardManager.exec_xmlrpc('updateUser', username=username, email=email, md5_passwordHash=password)
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
@@ -111,7 +124,6 @@ class IPBoardManager:
@staticmethod
def help_me():
"Random help me"
ret = IPBoardManager.exec_xmlrpc('helpMe')
return ret
@@ -120,13 +132,13 @@ class IPBoardManager:
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([g.replace(' ', '-') for g in groups])
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 not g in forum_groups:
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)

View File

@@ -1,27 +1,21 @@
from __future__ import unicode_literals
import logging
from django.conf import settings
import requests
import os
from django.db import connections
from passlib.hash import bcrypt
from django.utils import timezone
logger = logging.getLogger(__name__)
class Ips4Manager:
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)
@@ -30,7 +24,6 @@ class Ips4Manager:
hash_result = hash
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
joined_date = timezone.now
group = Ips4Manager.MEMBER_GROUP_ID
cursor = connections['ips4'].cursor()
cursor.execute(Ips4Manager.SQL_ADD_USER, [username, email, hash, salt, group])
@@ -53,7 +46,6 @@ class Ips4Manager:
def __generate_random_pass():
return os.urandom(8).encode('hex')
@staticmethod
def delete_user(id):
logger.debug("Deleting IPS4 user id %s" % id)
@@ -107,4 +99,4 @@ class Ips4Manager:
return plain_password
else:
logger.error("Unable to update ips4 user %s password" % username)
return ""
return ""

View File

@@ -1,18 +1,21 @@
from __future__ import unicode_literals
import logging
from django.conf import settings
import requests
import os
from django.db import connections
from passlib.hash import bcrypt
## requires yum install libffi-devel and pip install bcrypt
# requires yum install libffi-devel and pip install bcrypt
logger = logging.getLogger(__name__)
class marketManager:
SQL_ADD_USER = r"INSERT INTO fos_user (username, username_canonical, email, email_canonical, enabled, salt, password," \
r"locked, expired, roles, credentials_expired, characterid, characterName)" \
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"
@@ -22,7 +25,6 @@ class marketManager:
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(" ", "_")
@@ -56,7 +58,6 @@ class marketManager:
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)
@@ -66,8 +67,8 @@ class marketManager:
rounds_striped = hash_result.strip('$2a$13$')
salt = rounds_striped[:22]
username_clean = marketManager.__santatize_username(username)
if marketManager.check_username(username)== False:
if marketManager.check_user_email(username, email) == False:
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()

View File

@@ -1,10 +1,6 @@
from __future__ import unicode_literals
import os
import hashlib
import sys
import django
from django.db import connections
from django.conf import settings
from services.models import MumbleUser
@@ -12,7 +8,10 @@ import logging
logger = logging.getLogger(__name__)
class MumbleManager:
def __init__(self):
pass
@staticmethod
def __santatize_username(username):
@@ -41,10 +40,11 @@ class MumbleManager:
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]))
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)
model = MumbleUser.objects.create(username=username_clean, pwhash=pwhash)
MumbleUser.objects.create(username=username_clean, pwhash=pwhash)
return username_clean, password
else:
logger.warn("Mumble user %s already exists. Updating password")
@@ -57,13 +57,15 @@ class MumbleManager:
@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))
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]))
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)
model = MumbleUser.objects.create(username=username_clean, pwhash=pwhash)
MumbleUser.objects.create(username=username_clean, pwhash=pwhash)
return username_clean, password
else:
logger.warn("Mumble user %s already exists. Updating password")
@@ -102,7 +104,7 @@ class MumbleManager:
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 =''
groups = ''
for g in safe_groups:
groups = groups + g + ','
groups = groups.strip(',')

View File

@@ -1,9 +1,14 @@
from __future__ import unicode_literals
from django.utils import six
import re
import os
from urlparse import urlparse
try:
from urlparse import urlparse
except ImportError:
# python 3
from urllib.parse import urlparse
import xmpp
from django.contrib.auth.models import User
from django.contrib.auth.models import Group
import sleekxmpp
from django.conf import settings
import threading
from ofrestapi.users import Users as ofUsers
@@ -13,6 +18,7 @@ import logging
logger = logging.getLogger(__name__)
class OpenfireManager:
def __init__(self):
pass
@@ -38,6 +44,11 @@ class OpenfireManager:
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)
@@ -95,30 +106,33 @@ class OpenfireManager:
return ""
@staticmethod
def update_user_groups(username, password, groups):
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, basestring):
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:
if not g in remote_groups:
g = OpenfireManager._sanitize_groupname(g)
if g not in remote_groups:
add_groups.append(g)
for g in remote_groups:
if not g in 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))
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))
@@ -129,30 +143,58 @@ class OpenfireManager:
@staticmethod
def send_broadcast_message(group_name, broadcast_message):
logger.debug("Sending jabber ping to group %s with message %s" % (group_name, broadcast_message))
# create to address
client = xmpp.Client(settings.JABBER_URL)
client.connect(server=(settings.JABBER_SERVER, settings.JABBER_PORT))
client.auth(settings.BROADCAST_USER, settings.BROADCAST_USER_PASSWORD, 'broadcast')
to_address = group_name + '@' + settings.BROADCAST_SERVICE_NAME + '.' + settings.JABBER_URL
logger.debug("Determined ping to address: %s" % to_address)
message = xmpp.Message(to_address, broadcast_message)
message.setAttr('type', 'chat')
client.send(message)
client.Process(1)
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.")
client.disconnect()
logger.info("Sent jabber ping to group %s" % group_name)
class XmppThread (threading.Thread):
def __init__(self, threadID, name, counter, group, message,):
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 = threadID
self.threadID = thread_id
self.name = name
self.counter = counter
self.group = group
self.message = message
def run(self):
print "Starting " + self.name
OpenfireManager.send_broadcast_message(self.group, self.message)
print "Exiting " + self.name

View File

@@ -1,196 +0,0 @@
import logging
from django.conf import settings
import requests
import os
from django.db import connections
from passlib.hash import bcrypt
from eveonline.managers import EveManager
from authentication.managers import AuthServicesInfo
from eveonline.models import EveCharacter
from eveonline.models import EveApiKeyPair
logger = logging.getLogger(__name__)
class pathfinderManager:
SQL_ADD_USER = r"INSERT INTO user (name, email, password, active) VALUES (%s, %s, %s, %s)"
SQL_ADD_API = r"INSERT INTO user_api (userid, keyid, vCode, active) VALUES (%s, %s, %s, %s)"
SQL_ADD_CHARACTER = r"INSERT INTO user_character (userid, apiId, characterId, isMain) VALUES (%s, %s, %s, %s)"
SQL_GET_APIID = r"SELECT id, keyId FROM user_api WHERE userId = %s"
SQL_GET_USERID = r"SELECT id FROM user WHERE name = %s"
SQL_DISABLE_USER = r"UPDATE user SET active = '0' WHERE name = %s"
SQL_UPDATE_USER = r"UPDATE user SET active = '1', password = %s WHERE name = %s"
SQL_CHECK_USER = r"SELECT name FROM user WHERE name = %s"
SQL_CHECK_EMAIL = r"SELECT email from user WHERE email = %s"
SQL_SET_MAIN = r"UPDATE user_character SET isMain = 1 WHERE characterId = %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 for pathfinder username %s" % username)
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_CHECK_USER, [pathfinderManager.__santatize_username(username)])
row = cursor.fetchone()
if row:
logger.debug("Found user %s on pathfinder" % username)
return True
logger.debug("User %s not found on pathfinder" % username)
return False
@staticmethod
def update_user_info(username):
logger.debug("Updating pathfinder user %s" % username)
try:
username_clean = pathfinderManager.__santatize_username(username)
plain_password = pathfinderManager.__generate_random_pass()
passwd = bcrypt.encrypt(plain_password, rounds=10)
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_UPDATE_USER, [passwd, username_clean])
return username_clean, plain_password
except:
logger.debug("Pathfinder update user failed for %s" % username)
return "", ""
@staticmethod
def update_custom_password(username, plain_password):
logger.debug("Updating pathfinder user id %s password" % username)
if pathfinderManager.check_username(username):
username_clean = pathfinderManager.__santatize_username(username)
passwd = bcrypt.encrypt(plain_password, rounds=10)
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_UPDATE_USER, [passwd, username_clean])
return plain_password
else:
logger.error("Unable to update ips4 user %s password" % username)
return ""
@staticmethod
def disable_user(username):
logger.debug("Disabling user %s" % username)
if pathfinderManager.check_username(username) == True:
try:
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_DISABLE_USER, [pathfinderManager.__santatize_username(username)])
return True
except:
logger.debug("User %s not found cannot disable" % username)
@staticmethod
def add_user(username, email, charactername):
logger.debug("Adding new pathfinder user %s" % username)
plain_password = pathfinderManager.__generate_random_pass()
passwd = bcrypt.encrypt(plain_password, rounds=10)
username_clean = pathfinderManager.__santatize_username(username)
auth_id = pathfinderManager.get_authid_by_username(charactername)
if pathfinderManager.check_username(username)== False:
if pathfinderManager.check_email(username, email) == False:
try:
logger.debug("Adding user %s to pathfinder" % username)
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_ADD_USER, [username_clean,email, passwd, '1'])
path_id = pathfinderManager.get_pathfinder_user_id(username_clean)
api_keys = pathfinderManager.get_api_key_pairs(auth_id)
main_character = AuthServicesInfo.objects.get(user=auth_id).main_char_id
for keyId, key in api_keys.items():
cursor.execute(pathfinderManager.SQL_ADD_API, [path_id, keyId, key, '1'])
char_apis = pathfinderManager.get_char_id(auth_id)
for c,a in char_apis.items():
cursor.execute(pathfinderManager.SQL_ADD_CHARACTER, [path_id, (pathfinderManager.get_pathfinder_api_id(username, path_id)), c, '0'])
pathfinderManager.set_main_char(username, main_character)
return username_clean, plain_password
except:
logger.exception("Unsuccessful attempt at adding user %s to pathfinder on add_user" % username)
return "",""
else:
logger.debug("pathfinder username %s already exists Updating instead" % username)
username_clean, password = pathfinderManager.update_user_info(username)
return username_clean, password
else:
logger.debug("pathfinder username %s already exists Updating instead" % username)
username_clean, password = pathfinderManager.update_user_info(username)
return username_clean, password
@staticmethod
def set_main_char (username, main_character):
try:
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_SET_MAIN, [main_character])
except:
logger.debug("Failed setting main character for user %s"% username)
return ""
@staticmethod
def get_api_key_pairs(user_id):
char = EveCharacter.objects.all().filter(user_id=user_id)
api_list = dict()
for c in char:
api_pair = EveApiKeyPair.objects.get(api_id=c.api_id)
api_list[api_pair.api_id] = api_pair.api_key
return api_list
@staticmethod
def get_char_id(auth_id):
char = EveCharacter.objects.all().filter(user_id=auth_id)
char_list = dict()
for c in char:
char_list[c.character_id] = c.api_id
logger.debug("printing char list %s" % char_list)
return char_list
@staticmethod
def get_authid_by_username(username):
authid = EveCharacter.objects.get(character_name=username).user_id
return authid
@staticmethod
def get_pathfinder_user_id(username):
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_GET_USERID, [username])
row = cursor.fetchone()
if row:
logger.debug("Pathfinder ID for user %s is %s" % (username, row[0]))
return int(row[0])
else:
logger.debug("failed to get pathfinder ID for user %s" % username)
return ""
@staticmethod
def get_pathfinder_api_id(username, path_id):
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_GET_APIID, [path_id])
row = cursor.fetchone()
if row:
logger.debug("Pathfinder API ID for user %s is %s" % (username, row[0]))
return int(row[0])
else:
logger.debug("failed to get pathfinder API ID for user %s" % username)
return ""
@staticmethod
def check_email(username, email):
logger.debug("Checking if email %s exists for username %s" % (email,username))
cursor = connections['pathfinder'].cursor()
cursor.execute(pathfinderManager.SQL_CHECK_EMAIL, [email])
row = cursor.fetchone()
if row:
logger.debug("Found user %s email on pathfinder" % username)
return True
logger.debug("User %s email not found on pathfinder" % username)
return False

View File

@@ -1,5 +1,7 @@
from __future__ import unicode_literals
import os
import calendar
import re
from datetime import datetime
from passlib.apps import phpbb3_context
@@ -11,6 +13,7 @@ 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, " \
@@ -37,8 +40,9 @@ class Phpbb3Manager:
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_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"
@@ -70,6 +74,11 @@ class Phpbb3Manager:
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)
@@ -153,7 +162,8 @@ class Phpbb3Manager:
@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))
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)
@@ -195,7 +205,7 @@ class Phpbb3Manager:
Phpbb3Manager.update_groups(username, [])
logger.info("Disabled phpbb user %s" % username)
return True
except TypeError as e:
except TypeError:
logger.exception("TypeError occured while disabling user %s - failed to disable." % username)
return False
@@ -218,7 +228,7 @@ class Phpbb3Manager:
if userid is not None:
forum_groups = Phpbb3Manager.__get_all_groups()
user_groups = set(Phpbb3Manager.__get_user_groups(userid))
act_groups = set([g.replace(' ', '-') for g in groups])
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))
@@ -244,7 +254,9 @@ class Phpbb3Manager:
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))
logger.exception(
"Exception prevented removal of phpbb user %s with id %s from group %s with id %s" % (
username, userid, group, groupid))
pass
@staticmethod
@@ -267,7 +279,8 @@ class Phpbb3Manager:
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]))
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)
@@ -277,7 +290,8 @@ class Phpbb3Manager:
@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)))
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])

View File

@@ -1,15 +1,21 @@
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)"
@@ -36,7 +42,10 @@ class smfManager:
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():
@@ -44,7 +53,7 @@ class smfManager:
@staticmethod
def gen_hash(username_clean, passwd):
return hashlib.sha1((username_clean) + passwd).hexdigest()
return hashlib.sha1(username_clean + passwd).hexdigest()
@staticmethod
def santatize_username(username):
@@ -66,7 +75,6 @@ class smfManager:
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)
@@ -88,7 +96,6 @@ class smfManager:
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))
@@ -133,7 +140,8 @@ class smfManager:
@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))
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()
@@ -141,12 +149,13 @@ class smfManager:
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 :
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])
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)
@@ -157,7 +166,8 @@ class smfManager:
@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)))
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])
@@ -185,19 +195,18 @@ class smfManager:
if userid is not None:
forum_groups = smfManager.get_all_groups()
user_groups = set(smfManager.get_user_groups(userid))
act_groups = set([g.replace(' ', '-') for g in groups])
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 not g in forum_groups:
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))
@@ -230,11 +239,11 @@ class smfManager:
try:
pwhash = smfManager.gen_hash(username, password)
cursor.execute(smfManager.SQL_DIS_USER, [revoke_email, pwhash, username])
userid = smfManager.get_user_id(username)
smfManager.get_user_id(username)
smfManager.update_groups(username, [])
logger.info("Disabled smf user %s" % username)
return True
except TypeError as e:
except TypeError:
logger.exception("TypeError occured while disabling user %s - failed to disable." % username)
return False
@@ -247,14 +256,11 @@ class smfManager:
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]))
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,46 +1,49 @@
from __future__ import unicode_literals
from django.conf import settings
import json
import urllib2
import requests
import logging
logger = logging.getLogger(__name__)
class srpManager():
class srpManager:
def __init__(self):
pass
@staticmethod
def get_kill_id (killboard_link):
str = (killboard_link)
set = '0123456789'
kill_id = ''.join([c for c in str if c in set])
def get_kill_id(killboard_link):
num_set = '0123456789'
kill_id = ''.join([c for c in killboard_link if c in num_set])
return kill_id
@staticmethod
def get_kill_data (kill_id):
def get_kill_data(kill_id):
url = ("https://www.zkillboard.com/api/killID/%s" % kill_id)
request = urllib2.Request(url)
request.add_header('User-Agent',"%s Alliance Auth" % settings.DOMAIN)
request.add_header('Content-Type','application/json')
response = urllib2.urlopen(request)
result = json.load(response)[0]
headers = {
'User-Agent': "%s Alliance Auth" % settings.DOMAIN,
'Content-Type': 'application/json',
}
r = requests.get(url, headers=headers)
result = r.json()[0]
if result:
ship_type = result['victim']['shipTypeID']
logger.debug("Ship type for kill ID %s is determined to be %s" % (kill_id, ship_type))
ship_value = result['zkb']['totalValue']
logger.debug("total loss value for kill id %s is %s" %(kill_id, ship_value))
return (ship_type, ship_value)
logger.debug("total loss value for kill id %s is %s" % (kill_id, ship_value))
return ship_type, ship_value
else:
raise ValueError("Invalid Kill ID")
@staticmethod
def get_ship_name (ship_type):
def get_ship_name(ship_type):
url = ("https://jetbalsa.com/api/json.php/invTypes/%s" % ship_type)
request = urllib2.Request(url)
request.add_header('User-Agent',"%s Alliance Auth" % settings.DOMAIN)
request.add_header('Content-Type','application/json')
response = urllib2.urlopen(request)
result = json.load(response)
headers = {
'User-Agent': "%s Alliance Auth" % settings.DOMAIN,
'Content-Type': 'application/json',
}
r = requests.get(url, headers=headers)
result = r.json()
if result:
ship_name = result['typeName']
logger.debug("ship type %s determined to be %s" % (ship_type, ship_name))
@@ -48,13 +51,3 @@ class srpManager():
else:
logger.debug("ship type %s is invalid" % ship_type)
raise ValueError("Cannot get ship name")

View File

@@ -1,11 +1,13 @@
from __future__ import unicode_literals
from django.conf import settings
from services.managers.util.ts3 import TS3Server
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
@@ -117,10 +119,9 @@ class Teamspeak3Manager:
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()
server_groups = Teamspeak3Manager._group_list()
user_groups = Teamspeak3Manager._user_group_list(uid)
if not groupid in user_groups.values():
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})
@@ -130,7 +131,6 @@ class Teamspeak3Manager:
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()
server_groups = Teamspeak3Manager._group_list()
user_groups = Teamspeak3Manager._user_group_list(uid)
if str(groupid) in user_groups.values():
@@ -149,39 +149,45 @@ class Teamspeak3Manager:
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))
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)
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))
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.")
pass
@staticmethod
def add_user(username, corp_ticker):
username_clean = Teamspeak3Manager.__santatize_username(Teamspeak3Manager.__generate_username(username,
corp_ticker))
corp_ticker))
server = Teamspeak3Manager.__get_created_server()
token = ""
logger.debug("Adding user to TS3 server with cleaned username %s" % username_clean)
server_groups = Teamspeak3Manager._group_list()
if not settings.DEFAULT_AUTH_GROUP in server_groups:
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)
ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': alliance_group_id, 'tokenid2': 0,
'tokendescription': username_clean,
'tokencustomset': "ident=sso_uid value=%s" % username_clean})
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']
@@ -189,24 +195,27 @@ class Teamspeak3Manager:
return username_clean, token
except:
logger.exception("Failed to add teamspeak user %s - received response: %s" % (username_clean, ret))
return "",""
return "", ""
@staticmethod
def add_blue_user(username, corp_ticker):
username_clean = Teamspeak3Manager.__santatize_username(Teamspeak3Manager.__generate_username_blue(username,
corp_ticker))
corp_ticker))
server = Teamspeak3Manager.__get_created_server()
token = ""
logger.debug("Adding user to TS3 server with cleaned username %s" % username_clean)
server_groups = Teamspeak3Manager._group_list()
if not settings.DEFAULT_BLUE_GROUP in server_groups:
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)
ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': blue_group_id, 'tokenid2': 0,
'tokendescription': username_clean,
'tokencustomset': "ident=sso_uid value=%s" % username_clean})
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']
@@ -214,10 +223,7 @@ class Teamspeak3Manager:
return username_clean, token
except:
logger.exception("Failed to add blue teamspeak user %s - received response: %s" % (username_clean, ret))
return "",""
return "", ""
@staticmethod
def delete_user(uid):
@@ -235,7 +241,12 @@ class Teamspeak3Manager:
logger.exception("Failed to delete user id %s from TS3 - received response %s" % (uid, client))
return False
ret = server.send_command('clientdbdelete', {'cldbid': user})
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
@@ -291,4 +302,3 @@ class Teamspeak3Manager:
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 +1,2 @@
from __future__ import unicode_literals
__author__ = 'r4stl1n'

View File

@@ -1,8 +1,9 @@
from __future__ import unicode_literals
import socket
import logging
class ConnectionError():
class ConnectionError:
def __init__(self, ip, port):
self.ip = ip
self.port = port
@@ -22,8 +23,7 @@ ts3_escape = {'/': r"\/",
"\t": r'\t',
"\v": r'\v'}
class TS3Proto():
class TS3Proto:
bytesin = 0
bytesout = 0
@@ -66,7 +66,7 @@ class TS3Proto():
while True:
resp = self._sockfile.readline()
resp = self.parse_command(resp)
if not 'command' in resp:
if 'command' not in resp:
data.append(resp)
else:
break
@@ -78,7 +78,7 @@ class TS3Proto():
else:
return data[0]
else:
return resp['keys']['id']
raise TeamspeakError(resp['keys']['id'])
def construct_command(self, command, keys=None, opts=None):
"""
@@ -139,7 +139,7 @@ class TS3Proto():
v = [v[0], '='.join(v[1:])]
key, value = v
keys[key] = self._unescape_str(value)
elif (not v == ['']):
elif not v == ['']:
if v[0][0] and v[0][0] == '-':
# Option
opts.append(v[0][1:])
@@ -159,9 +159,10 @@ class TS3Proto():
@type value: string/int
"""
if isinstance(value, int): return "%d" % value
if isinstance(value, int):
return "%d" % value
value = value.replace("\\", r'\\')
for i, j in ts3_escape.iteritems():
for i, j in ts3_escape:
value = value.replace(i, j)
return value
@@ -173,13 +174,13 @@ class TS3Proto():
@type value: string/int
"""
if isinstance(value, int): return "%d" % value
if isinstance(value, int):
return "%d" % value
value = value.replace(r"\\", "\\")
for i, j in ts3_escape.iteritems():
for i, j in ts3_escape:
value = value.replace(j, i)
return value
def send(self, payload):
if self._connected:
self._log.debug('Sent: %s' % payload)
@@ -230,7 +231,7 @@ class TS3Server(TS3Proto):
"""
Send a global message to the current Virtual Server
@param msg: Message
@type ip: str
@type msg: str
"""
if self._connected:
return self.send_command('gm', keys={'msg': msg})
@@ -243,3 +244,213 @@ class TS3Server(TS3Proto):
"""
if self._connected and id > 0:
self.send_command('use', keys={'sid': id})
class TeamspeakError:
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,3 +1,4 @@
from __future__ import unicode_literals
import os
import requests
import json
@@ -8,130 +9,131 @@ 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
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 __sanitize_username(username):
sanitized = username.replace(" ", "_")
return sanitized
@staticmethod
def __generate_password():
return os.urandom(8).encode('hex')
@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 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):
@staticmethod
def add_user(username, email):
sanitized = XenForoManager.__sanitize_username(username)
password = XenForoManager.__generate_password();
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'
}
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
r = XenForoManager.exec_http_request(data)
response = {
'response': {
'message': r.text,
'status_code': r.status_code
}
}
data.update(response)
return 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
@staticmethod
def reset_password(username):
response = {
'response': {
'message': r.text,
'status_code': r.status_code
}
}
data.update(response)
return data
password = XenForoManager.__generate_password();
@staticmethod
def reset_password(username):
data = {
'action': 'editUser',
'user': username,
'password': password
}
password = XenForoManager.__generate_password()
r = XenForoManager.exec_http_request(data)
data = {
'action': 'editUser',
'user': username,
'password': password
}
response = {
'response': {
'message': r.text,
'status_code': r.status_code
}
}
data.update(response)
return data
r = XenForoManager.exec_http_request(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
response = {
'response': {
'message': r.text,
'status_code': r.status_code
}
}
data.update(response)
return data
@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 disable_user(username):
data = {
'action': 'editUser',
'user': username,
'remove_groups': settings.XENFORO_DEFAULT_GROUP
}
r = XenForoManager.exec_http_request(data)
return r
@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
@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

View File

@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 21:40
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0008_alter_user_username_max_length'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='AuthTS',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('auth_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
],
options={
'verbose_name': 'Auth / TS Group',
},
),
migrations.CreateModel(
name='DiscordAuthToken',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.CharField(max_length=254, unique=True)),
('token', models.CharField(max_length=254)),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='GroupCache',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('groups', models.TextField(default={})),
('service', models.CharField(choices=[(b'discourse', b'discourse'), (b'discord', b'discord')], max_length=254, unique=True)),
],
),
migrations.CreateModel(
name='MumbleUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('username', models.CharField(max_length=254, unique=True)),
('pwhash', models.CharField(max_length=40)),
('groups', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='TSgroup',
fields=[
('ts_group_id', models.IntegerField(primary_key=True, serialize=False)),
('ts_group_name', models.CharField(max_length=30)),
],
options={
'verbose_name': 'TS Group',
},
),
migrations.CreateModel(
name='UserTSgroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ts_group', models.ManyToManyField(to='services.TSgroup')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'User TS Group',
},
),
migrations.AddField(
model_name='authts',
name='ts_group',
field=models.ManyToManyField(to='services.TSgroup'),
),
]

View File

@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-10-16 01:35
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('services', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='discordauthtoken',
name='user',
),
migrations.DeleteModel(
name='DiscordAuthToken',
),
]

View File

View File

@@ -1,44 +1,45 @@
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models
from django.contrib.auth.models import Group, User
@python_2_unicode_compatible
class TSgroup(models.Model):
ts_group_id = models.IntegerField(primary_key=True)
ts_group_name = models.CharField(max_length=30)
class Meta:
verbose_name='TS Group'
verbose_name = 'TS Group'
def __str__(self):
return self.ts_group_name
@python_2_unicode_compatible
class AuthTS(models.Model):
auth_group = models.ForeignKey('auth.Group')
ts_group = models.ManyToManyField(TSgroup)
class Meta:
verbose_name='Auth / TS Group'
verbose_name = 'Auth / TS Group'
def __str__(self):
return self.auth_group.name
@python_2_unicode_compatible
class UserTSgroup(models.Model):
user = models.ForeignKey('auth.User')
ts_group = models.ManyToManyField(TSgroup)
class Meta:
verbose_name='User TS Group'
verbose_name = 'User TS Group'
def __str__(self):
return self.user.name
class DiscordAuthToken(models.Model):
email = models.CharField(max_length=254, unique=True)
token = models.CharField(max_length=254)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
def __str__(self):
output = "Discord Token for email %s user %s" % (self.email, self.user)
return output.encode('utf-8')
@python_2_unicode_compatible
class MumbleUser(models.Model):
username = models.CharField(max_length=254, unique=True)
pwhash = models.CharField(max_length=40)
@@ -47,6 +48,8 @@ class MumbleUser(models.Model):
def __str__(self):
return self.username
@python_2_unicode_compatible
class GroupCache(models.Model):
SERVICE_CHOICES = (
("discourse", "discourse"),

98
services/signals.py Normal file
View File

@@ -0,0 +1,98 @@
from __future__ import unicode_literals
from django.db.models.signals import m2m_changed
from django.db.models.signals import post_save
from django.db.models.signals import pre_save
from django.db.models.signals import post_delete
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from django.contrib.auth.models import User
import logging
from services.tasks import update_jabber_groups
from services.tasks import update_mumble_groups
from services.tasks import update_forum_groups
from services.tasks import update_ipboard_groups
from services.tasks import update_discord_groups
from services.tasks import update_teamspeak3_groups
from services.tasks import update_discourse_groups
from services.tasks import update_smf_groups
from authentication.tasks import set_state
from authentication.tasks import disable_member
from authentication.models import AuthServicesInfo
from services.models import AuthTS
logger = logging.getLogger(__name__)
@receiver(m2m_changed, sender=User.groups.through)
def m2m_changed_user_groups(sender, instance, action, *args, **kwargs):
logger.debug("Received m2m_changed from %s groups with action %s" % (instance, action))
if action == "post_add" or action == "post_remove" or action == "post_clear":
logger.debug("Triggering service group update for %s" % instance)
auth, c = AuthServicesInfo.objects.get_or_create(user=instance)
if auth.jabber_username:
update_jabber_groups.delay(instance.pk)
if auth.teamspeak3_uid:
update_teamspeak3_groups.delay(instance.pk)
if auth.forum_username:
update_forum_groups.delay(instance.pk)
if auth.smf_username:
update_smf_groups.delay(instance.pk)
if auth.ipboard_username:
update_ipboard_groups.delay(instance.pk)
if auth.discord_uid:
update_discord_groups.delay(instance.pk)
if auth.mumble_username:
update_mumble_groups.delay(instance.pk)
if auth.discourse_username:
update_discourse_groups.delay(instance.pk)
if auth.smf_username:
update_smf_groups.delay(instance.pk)
def trigger_all_ts_update():
for auth in AuthServicesInfo.objects.filter(teamspeak3_uid__isnull=False):
update_teamspeak3_groups.delay(auth.user.pk)
@receiver(m2m_changed, sender=AuthTS.ts_group.through)
def m2m_changed_authts_group(sender, instance, action, *args, **kwargs):
logger.debug("Received m2m_changed from %s ts_group with action %s" % (instance, action))
if action == "post_add" or action == "post_remove":
trigger_all_ts_update()
@receiver(post_save, sender=AuthTS)
def post_save_authts(sender, instance, *args, **kwargs):
logger.debug("Received post_save from %s" % instance)
trigger_all_ts_update()
@receiver(post_delete, sender=AuthTS)
def post_delete_authts(sender, instance, *args, **kwargs):
logger.debug("Received post_delete signal from %s" % instance)
trigger_all_ts_update()
@receiver(pre_delete, sender=User)
def pre_delete_user(sender, instance, *args, **kwargs):
logger.debug("Received pre_delete from %s" % instance)
disable_member(instance)
@receiver(pre_save, sender=User)
def pre_save_user(sender, instance, *args, **kwargs):
logger.debug("Received pre_save from %s" % instance)
# check if user is being marked active/inactive
if not instance.pk:
# new model being created
return
try:
old_instance = User.objects.get(pk=instance.pk)
if old_instance.is_active and not instance.is_active:
logger.info("Disabling services for inactivation of user %s" % instance)
disable_member(instance)
elif instance.is_active and not old_instance.is_active:
logger.info("Assessing state of reactivated user %s" % instance)
set_state(instance)
except User.DoesNotExist:
pass

View File

@@ -1,20 +1,47 @@
from authentication.models import AuthServicesInfo
from celerytask.models import SyncGroupCache
from __future__ import unicode_literals
from django.conf import settings
import logging
from django.contrib.auth.models import User
from celery import task
from services.models import UserTSgroup
from services.models import AuthTS
from services.models import TSgroup
from services.models import DiscordAuthToken
from services.models import MumbleUser
from authentication.managers import AuthServicesInfoManager
from authentication.models import AuthServicesInfo
from services.managers.openfire_manager import OpenfireManager
from services.managers.phpbb3_manager import Phpbb3Manager
from services.managers.mumble_manager import MumbleManager
from services.managers.ipboard_manager import IPBoardManager
from services.managers.teamspeak3_manager import Teamspeak3Manager
from services.managers.discord_manager import DiscordOAuthManager
from services.managers.xenforo_manager import XenForoManager
from services.managers.market_manager import marketManager
from services.managers.discourse_manager import DiscourseManager
from services.managers.smf_manager import smfManager
from services.managers.util.ts3 import TeamspeakError
from authentication.states import MEMBER_STATE, BLUE_STATE
from notifications import notify
from celery.task import periodic_task
from celery.task.schedules import crontab
logger = logging.getLogger(__name__)
@periodic_task(run_every=crontab(minute="*/30"))
def run_ts3_group_update():
if settings.ENABLE_AUTH_TEAMSPEAK3 or settings.ENABLE_BLUE_TEAMSPEAK3:
logger.debug("TS3 installed. Syncing local group objects.")
Teamspeak3Manager._sync_ts_group_db()
def disable_teamspeak():
if settings.ENABLE_AUTH_TEAMSPEAK3:
logger.warn("ENABLE_AUTH_TEAMSPEAK3 still True, after disabling users will still be able to create teamspeak accounts")
logger.warn(
"ENABLE_AUTH_TEAMSPEAK3 still True, after disabling users will still be able to create teamspeak accounts")
if settings.ENABLE_BLUE_TEAMSPEAK3:
logger.warn("ENABLE_BLUE_TEAMSPEAK3 still True, after disabling blues will still be able to create teamspeak accounts")
logger.warn(
"ENABLE_BLUE_TEAMSPEAK3 still True, after disabling blues will still be able to create teamspeak accounts")
for auth in AuthServicesInfo.objects.all():
if auth.teamspeak3_uid:
logger.info("Clearing %s Teamspeak3 UID" % auth.user)
@@ -32,6 +59,7 @@ def disable_teamspeak():
TSgroup.objects.all().delete()
logger.info("Teamspeak3 disabled")
def disable_forum():
if settings.ENABLE_AUTH_FORUM:
logger.warn("ENABLE_AUTH_FORUM still True, after disabling users will still be able to create forum accounts")
@@ -46,8 +74,7 @@ def disable_forum():
logger.info("Clearing %s forum password" % auth.user)
auth.forum_password = ''
auth.save()
logger.info("Deleting all SyncGroupCache models for forum")
SyncGroupCache.objects.filter(servicename="forum").delete()
def disable_jabber():
if settings.ENABLE_AUTH_JABBER:
@@ -63,8 +90,7 @@ def disable_jabber():
logger.info("Clearing %s jabber password" % auth.user)
auth.jabber_password = ''
auth.save()
logger.info("Deleting all SyncGroupCache models for jabber")
SyncGroupCache.objects.filter(servicename="jabber").delete()
def disable_mumble():
if settings.ENABLE_AUTH_MUMBLE:
@@ -80,16 +106,17 @@ def disable_mumble():
logger.info("Clearing %s mumble password" % auth.user)
auth.mumble_password = ''
auth.save()
logger.info("Deleting all SyncGroupCache models for mumble")
SyncGroupCache.objects.filter(servicename="mumble").delete()
logger.info("Deleting all MumbleUser models")
MumbleUser.objects.all().delete()
def disable_ipboard():
if settings.ENABLE_AUTH_IPBOARD:
logger.warn("ENABLE_AUTH_IPBOARD still True, after disabling users will still be able to create IPBoard accounts")
logger.warn(
"ENABLE_AUTH_IPBOARD still True, after disabling users will still be able to create IPBoard accounts")
if settings.ENABLE_BLUE_IPBOARD:
logger.warn("ENABLE_BLUE_IPBOARD still True, after disabling blues will still be able to create IPBoard accounts")
logger.warn(
"ENABLE_BLUE_IPBOARD still True, after disabling blues will still be able to create IPBoard accounts")
for auth in AuthServicesInfo.objects.all():
if auth.ipboard_username:
logger.info("Clearing %s ipboard username" % auth.user)
@@ -99,8 +126,6 @@ def disable_ipboard():
logger.info("Clearing %s ipboard password" % auth.user)
auth.ipboard_password = ''
auth.save()
logger.info("Deleting all SyncGroupCache models for ipboard")
SyncGroupCache.objects.filter(servicename="ipboard").delete()
def disable_discord():
@@ -113,5 +138,349 @@ def disable_discord():
logger.info("Clearing %s Discord UID" % auth.user)
auth.discord_uid = ''
auth.save()
logger.info("Deleting all DiscordAuthToken models")
DiscordAuthToken.objects.all().delete()
def deactivate_services(user):
change = False
logger.debug("Deactivating services for user %s" % user)
authinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
if authinfo.mumble_username and authinfo.mumble_username != "":
logger.debug("User %s has mumble account %s. Deleting." % (user, authinfo.mumble_username))
MumbleManager.delete_user(authinfo.mumble_username)
AuthServicesInfoManager.update_user_mumble_info("", user)
change = True
if authinfo.jabber_username and authinfo.jabber_username != "":
logger.debug("User %s has jabber account %s. Deleting." % (user, authinfo.jabber_username))
OpenfireManager.delete_user(authinfo.jabber_username)
AuthServicesInfoManager.update_user_jabber_info("", user)
change = True
if authinfo.forum_username and authinfo.forum_username != "":
logger.debug("User %s has forum account %s. Deleting." % (user, authinfo.forum_username))
Phpbb3Manager.disable_user(authinfo.forum_username)
AuthServicesInfoManager.update_user_forum_info("", user)
change = True
if authinfo.ipboard_username and authinfo.ipboard_username != "":
logger.debug("User %s has ipboard account %s. Deleting." % (user, authinfo.ipboard_username))
IPBoardManager.disable_user(authinfo.ipboard_username)
AuthServicesInfoManager.update_user_ipboard_info("", user)
change = True
if authinfo.teamspeak3_uid and authinfo.teamspeak3_uid != "":
logger.debug("User %s has mumble account %s. Deleting." % (user, authinfo.teamspeak3_uid))
Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid)
AuthServicesInfoManager.update_user_teamspeak3_info("", "", user)
change = True
if authinfo.discord_uid and authinfo.discord_uid != "":
logger.debug("User %s has discord account %s. Deleting." % (user, authinfo.discord_uid))
DiscordOAuthManager.delete_user(authinfo.discord_uid)
AuthServicesInfoManager.update_user_discord_info("", user)
change = True
if authinfo.xenforo_username and authinfo.xenforo_password != "":
logger.debug("User %s has a XenForo account %s. Deleting." % (user, authinfo.xenforo_username))
XenForoManager.disable_user(authinfo.xenforo_username)
AuthServicesInfoManager.update_user_xenforo_info("", user)
change = True
if authinfo.market_username and authinfo.market_username != "":
logger.debug("User %s has a Market account %s. Deleting." % (user, authinfo.market_username))
marketManager.disable_user(authinfo.market_username)
AuthServicesInfoManager.update_user_market_info("", user)
change = True
if authinfo.discourse_username and authinfo.discourse_username != "":
logger.debug("User %s has a Discourse account %s. Deleting." % (user, authinfo.discourse_username))
DiscourseManager.delete_user(authinfo.discourse_username)
AuthServicesInfoManager.update_user_discourse_info("", user)
change = True
if authinfo.smf_username and authinfo.smf_username != "":
logger.debug("User %s has a SMF account %s. Deleting." % (user, authinfo.smf_username))
smfManager.disable_user(authinfo.smf_username)
AuthServicesInfoManager.update_user_smf_info("", user)
change = True
if change:
notify(user, "Services Disabled", message="Your services accounts have been disabled.", level="danger")
@task
def validate_services(user, state):
if state == MEMBER_STATE:
setting_string = 'AUTH'
elif state == BLUE_STATE:
setting_string = 'BLUE'
else:
deactivate_services(user)
return
logger.debug('Ensuring user %s services are available to state %s' % (user, state))
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
if auth.mumble_username and not getattr(settings, 'ENABLE_%s_MUMBLE' % setting_string, False):
MumbleManager.delete_user(auth.mumble_username)
AuthServicesInfoManager.update_user_mumble_info("", user)
notify(user, 'Mumble Account Disabled', level='danger')
if auth.jabber_username and not getattr(settings, 'ENABLE_%s_JABBER' % setting_string, False):
OpenfireManager.delete_user(auth.jabber_username)
AuthServicesInfoManager.update_user_jabber_info("", user)
notify(user, 'Jabber Account Disabled', level='danger')
if auth.forum_username and not getattr(settings, 'ENABLE_%s_FORUM' % setting_string, False):
Phpbb3Manager.disable_user(auth.forum_username)
AuthServicesInfoManager.update_user_forum_info("", user)
notify(user, 'Forum Account Disabled', level='danger')
if auth.ipboard_username and not getattr(settings, 'ENABLE_%s_IPBOARD' % setting_string, False):
IPBoardManager.disable_user(auth.ipboard_username)
AuthServicesInfoManager.update_user_ipboard_info("", user)
notify(user, 'IPBoard Account Disabled', level='danger')
if auth.teamspeak3_uid and not getattr(settings, 'ENABLE_%s_TEAMSPEAK' % setting_string, False):
Teamspeak3Manager.delete_user(auth.teamspeak3_uid)
AuthServicesInfoManager.update_user_teamspeak3_info("", "", user)
notify(user, 'TeamSpeak3 Account Disabled', level='danger')
if auth.discord_uid and not getattr(settings, 'ENABLE_%s_DISCORD' % setting_string, False):
DiscordOAuthManager.delete_user(auth.discord_uid)
AuthServicesInfoManager.update_user_discord_info("", user)
notify(user, 'Discord Account Disabled', level='danger')
if auth.xenforo_username and not getattr(settings, 'ENABLE_%s_XENFORO' % setting_string, False):
XenForoManager.disable_user(auth.xenforo_username)
AuthServicesInfoManager.update_user_xenforo_info("", user)
notify(user, 'XenForo Account Disabled', level='danger')
if auth.market_username and not getattr(settings, 'ENABLE_%s_MARKET' % setting_string, False):
marketManager.disable_user(auth.market_username)
AuthServicesInfoManager.update_user_market_info("", user)
notify(user, 'Alliance Market Account Disabled', level='danger')
if auth.discourse_username and not getattr(settings, 'ENABLE_%s_DISCOURSE' % setting_string, False):
DiscourseManager.delete_user(auth.discourse_username)
AuthServicesInfoManager.update_user_discourse_info("", user)
notify(user, 'Discourse Account Disabled', level='danger')
if auth.smf_username and not getattr(settings, 'ENABLE_%s_SMF' % setting_string, False):
smfManager.disable_user(auth.smf_username)
AuthServicesInfoManager.update_user_smf_info(auth.smf_username, user)
notify(user, "SMF Account Disabled", level='danger')
@task
def update_jabber_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating jabber groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s jabber groups to %s" % (user, groups))
try:
OpenfireManager.update_user_groups(authserviceinfo.jabber_username, groups)
except:
logger.exception("Jabber group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s jabber groups." % user)
@task
def update_all_jabber_groups():
logger.debug("Updating ALL jabber groups")
for user in AuthServicesInfo.objects.exclude(jabber_username__exact=''):
update_jabber_groups.delay(user.user_id)
@task
def update_mumble_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating mumble groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s mumble groups to %s" % (user, groups))
try:
MumbleManager.update_groups(authserviceinfo.mumble_username, groups)
except:
logger.exception("Mumble group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s mumble groups." % user)
@task
def update_all_mumble_groups():
logger.debug("Updating ALL mumble groups")
for user in AuthServicesInfo.objects.exclude(mumble_username__exact=''):
update_mumble_groups.delay(user.user_id)
@task
def update_forum_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating forum groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s forum groups to %s" % (user, groups))
try:
Phpbb3Manager.update_groups(authserviceinfo.forum_username, groups)
except:
logger.exception("Phpbb group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s forum groups." % user)
@task
def update_all_forum_groups():
logger.debug("Updating ALL forum groups")
for user in AuthServicesInfo.objects.exclude(forum_username__exact=''):
update_forum_groups.delay(user.user_id)
@task
def update_smf_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating smf groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s smf groups to %s" % (user, groups))
try:
smfManager.update_groups(authserviceinfo.smf_username, groups)
except:
logger.exception("smf group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s smf groups." % user)
@task
def update_all_smf_groups():
logger.debug("Updating ALL smf groups")
for user in AuthServicesInfo.objects.exclude(smf_username__exact=''):
update_smf_groups.delay(user.user_id)
@task
def update_ipboard_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating user %s ipboard groups." % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s ipboard groups to %s" % (user, groups))
try:
IPBoardManager.update_groups(authserviceinfo.ipboard_username, groups)
except:
logger.exception("IPBoard group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s ipboard groups." % user)
@task
def update_all_ipboard_groups():
logger.debug("Updating ALL ipboard groups")
for user in AuthServicesInfo.objects.exclude(ipboard_username__exact=''):
update_ipboard_groups.delay(user.user_id)
@task
def update_teamspeak3_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating user %s teamspeak3 groups" % user)
usergroups = user.groups.all()
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = {}
for usergroup in usergroups:
filtered_groups = AuthTS.objects.filter(auth_group=usergroup)
if filtered_groups:
for filtered_group in filtered_groups:
for ts_group in filtered_group.ts_group.all():
groups[ts_group.ts_group_name] = ts_group.ts_group_id
logger.debug("Updating user %s teamspeak3 groups to %s" % (user, groups))
try:
Teamspeak3Manager.update_groups(authserviceinfo.teamspeak3_uid, groups)
logger.debug("Updated user %s teamspeak3 groups." % user)
except TeamspeakError as e:
logger.error("Error occured while syncing TS groups for %s: %s" % (user, str(e)))
raise self.retry(countdown=60*10)
@task
def update_all_teamspeak3_groups():
logger.debug("Updating ALL teamspeak3 groups")
for user in AuthServicesInfo.objects.exclude(teamspeak3_uid__exact=''):
update_teamspeak3_groups.delay(user.user_id)
@task
def update_discord_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating discord groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
logger.debug("No syncgroups found for user. Adding empty group.")
groups.append('empty')
logger.debug("Updating user %s discord groups to %s" % (user, groups))
try:
DiscordOAuthManager.update_groups(authserviceinfo.discord_uid, groups)
except:
logger.exception("Discord group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s discord groups." % user)
@task
def update_all_discord_groups():
logger.debug("Updating ALL discord groups")
for user in AuthServicesInfo.objects.exclude(discord_uid__exact=''):
update_discord_groups.delay(user.user_id)
@task
def update_discord_nickname(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating discord nickname for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
character = EveManager.get_character_by_id(authserviceinfo.main_char_id)
logger.debug("Updating user %s discord nickname to %s" % (user, character.character_name))
try:
DiscordOAuthManager.update_nickname(authserviceinfo.discord_uid, character.character_name)
except:
logger.exception("Discord nickname sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s discord nickname." % user)
@task
def update_all_discord_nicknames():
logger.debug("Updating ALL discord nicknames")
for user in AuthServicesInfo.objects.exclude(discord_uid__exact=''):
update_discord_nickname(user.user_id)
@task
def update_discourse_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating discourse groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
logger.debug("No syncgroups found for user. Adding empty group.")
groups.append('empty')
logger.debug("Updating user %s discourse groups to %s" % (user, groups))
try:
DiscourseManager.update_groups(authserviceinfo.discourse_username, groups)
except:
logger.warn("Discourse group sync failed for %s, retrying in 10 mins" % user, exc_info=True)
raise self.retry(countdown=60 * 10)
logger.debug("Updated user %s discourse groups." % user)
@task
def update_all_discourse_groups():
logger.debug("Updating ALL discourse groups")
for user in AuthServicesInfo.objects.exclude(discourse_username__exact=''):
update_discourse_groups.delay(user.user_id)

File diff suppressed because it is too large Load Diff