From 7e05054854f02cf4e4709a622179f0d7691675da Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 03:43:02 +0000 Subject: [PATCH 01/30] Initial work on Discord integration. Manually created REST API manager as per the documented functions. Attempting to integrade discord-py wrapper, unsuccesful thusfar. Addresses #88 --- services/managers/discord_manager.py | 8 + services/managers/util/discord_api_manager.py | 138 ++++++++++++++++++ services/managers/util/discord_client.py | 17 +++ 3 files changed, 163 insertions(+) create mode 100644 services/managers/discord_manager.py create mode 100644 services/managers/util/discord_api_manager.py create mode 100644 services/managers/util/discord_client.py diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py new file mode 100644 index 00000000..31e1a445 --- /dev/null +++ b/services/managers/discord_manager.py @@ -0,0 +1,8 @@ +from services.managers.util import discord_client +from django.conf import settings + +class DiscordManager: + def __init__(self, discord_client): + self.discord_client = discord_client + discord_client.client.run() + super().__init__() diff --git a/services/managers/util/discord_api_manager.py b/services/managers/util/discord_api_manager.py new file mode 100644 index 00000000..fc285880 --- /dev/null +++ b/services/managers/util/discord_api_manager.py @@ -0,0 +1,138 @@ +import requests +import json +from django.conf import settings + +DISCORD_URL = "https://discordapp.com/api" + +class DiscordManager: + + def __init__(self): + pass + + @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)) + r.raise_for_status() + return r.json()['token'] + + @staticmethod + def add_server(name): + data = {"name": name} + custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds" + r = requests.post(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + return r.json() + + @staticmethod + def rename_server(server_id, name): + data = {"name": name} + custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + return r.json() + + @staticmethod + def delete_server(server_id): + custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + r = requests.delete(path, headers=custom_headers) + r.raise_for_status() + + @staticmethod + def get_members(server_id): + custom_headers = {'accept':'application/json', 'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/members" + r = requests.get(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def get_bans(server_id): + custom_headers = {'accept':'application/json', 'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans" + r = requests.get(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def ban_user(server_id, user_id, delete_message_age=0): + custom_headers = {'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) + "?delete-message-days=" + str(delete_message_age) + r = requests.put(path, headers=custom_headers) + r.raise_for_status() + + @staticmethod + def unban_user(server_id, user_id): + custom_headers = {'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) + r = requests.delete(path, headers=custom_headers) + r.raise_for_status() + + @staticmethod + def generate_role(server_id): + custom_headers = {'accept':'application/json', 'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles" + r = requests.post(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def edit_role(server_id, role_id, name, color=0, hoist=True, permissions=36953089): + custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} + data = { + 'color': color, + 'hoist': hoist, + 'name': name, + 'permissions': permissions, + } + path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles/" + str(role_id) + r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + return r.json() + + + @staticmethod + def delete_role(server_id, role_id): + custom_headers = {'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(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() + + @staticmethod + def accept_invite(invite_id): + custom_headers = {'accept': 'application/json'} + path = DISCORD_URL + "/invite/" + str(invite_id) + r = requests.post(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def create_invite(channel_id): + custom_headers = {'authorization': DiscordManager.get_auth_token()} + path = DISCORD_URL + "/channels/" + str(channel_id) + "/invites" + r = requests.post(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def delete_invite(invite_id): + custom_headers = {'accept': 'application/json'} + path = DISCORD_URL + "/invite/" + str(invite_id) + r = requests.delete(path, headers=custom_headers) + r.raise_for_status() diff --git a/services/managers/util/discord_client.py b/services/managers/util/discord_client.py new file mode 100644 index 00000000..c5dd722a --- /dev/null +++ b/services/managers/util/discord_client.py @@ -0,0 +1,17 @@ +import discord +from django.conf import settings + + +client = discord.Client() + +print('Logging in to Discord as ' + settings.DISCORD_USER_EMAIL) +client.login(settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) +if not client.is_logged_in: + print('Logging in to Discord failed') + raise ValueError('Supplied Discord credentials failed login') + +@client.event +def on_ready(): + server = client.servers[0] + user = client.user + print('Connected as ' + user.name) From 4383e9314dac748f6e6b456a160b074d6407ad98 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 04:00:31 +0000 Subject: [PATCH 02/30] Corrected missing header for delete_invite --- services/managers/util/discord_api_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/managers/util/discord_api_manager.py b/services/managers/util/discord_api_manager.py index fc285880..0adfcdb2 100644 --- a/services/managers/util/discord_api_manager.py +++ b/services/managers/util/discord_api_manager.py @@ -132,7 +132,7 @@ class DiscordManager: @staticmethod def delete_invite(invite_id): - custom_headers = {'accept': 'application/json'} + custom_headers = {'authorization': DiscordManager.get_auth_token()} path = DISCORD_URL + "/invite/" + str(invite_id) r = requests.delete(path, headers=custom_headers) r.raise_for_status() From c51b8c77e68802be57cad69e5980cc81f350681e Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 21:47:06 +0000 Subject: [PATCH 03/30] Consolidated API manager and service manager. Initial service functions added to DiscordManager. --- services/managers/discord_manager.py | 264 +++++++++++++++++- services/managers/util/discord_api_manager.py | 138 --------- 2 files changed, 259 insertions(+), 143 deletions(-) delete mode 100644 services/managers/util/discord_api_manager.py diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 31e1a445..b08dcde7 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -1,8 +1,262 @@ -from services.managers.util import discord_client +import requests +import json from django.conf import settings +import re + +DISCORD_URL = "https://discordapp.com/api" + +class DiscordAPIManager: + + def __init__(self): + pass + + @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)) + r.raise_for_status() + return r.json()['token'] + + @staticmethod + def add_server(name): + data = {"name": name} + custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds" + r = requests.post(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + return r.json() + + @staticmethod + def rename_server(server_id, name): + data = {"name": name} + custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + return r.json() + + @staticmethod + def delete_server(server_id): + custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + r = requests.delete(path, headers=custom_headers) + r.raise_for_status() + + @staticmethod + def get_members(server_id): + custom_headers = {'accept':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/members" + r = requests.get(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def get_bans(server_id): + custom_headers = {'accept':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans" + r = requests.get(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def ban_user(server_id, user_id, delete_message_age=0): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) + "?delete-message-days=" + str(delete_message_age) + r = requests.put(path, headers=custom_headers) + r.raise_for_status() + + @staticmethod + def unban_user(server_id, user_id): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) + r = requests.delete(path, headers=custom_headers) + r.raise_for_status() + + @staticmethod + def generate_role(server_id): + custom_headers = {'accept':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles" + r = requests.post(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def edit_role(server_id, role_id, name, color=0, hoist=True, permissions=36953089): + custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + data = { + 'color': color, + 'hoist': hoist, + 'name': name, + 'permissions': permissions, + } + path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles/" + str(role_id) + r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + return r.json() + + + @staticmethod + def delete_role(server_id, role_id): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(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() + + @staticmethod + def accept_invite(invite_id): + custom_headers = {'accept': 'application/json'} + path = DISCORD_URL + "/invite/" + str(invite_id) + r = requests.post(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def create_invite(server_id, max_age=0, max_users=1, temporary=True, xkcdpass=False): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/channels/" + str(server_id) + "/invites" + data = { + 'max_age': max_age, + 'max_users': max_users, + 'temporary': temporary, + 'xkcdpass': xkcdpass, + } + r = requests.post(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + return r.json() + + @staticmethod + def delete_invite(invite_id): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/invite/" + str(invite_id) + r = requests.delete(path, headers=custom_headers) + r.raise_for_status() + + @staticmethod + def set_roles(server_id, user_id, role_ids): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token(), 'content-type':'application/json'} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/members/" + str(user_id) + data = { 'roles': role_ids } + r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + + @staticmethod + def register_user(server_id, username, invite_code): + custom_headers = {'content-type': 'application/json'} + data = { + 'fingerprint': None, + 'username': username, + 'invite': invite_code, + } + path = DISCORD_URL + "/auth/register" + r = requests.post(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() + + @staticmethod + def kick_user(server_id, user_id): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/members/" + str(user_id) + r = requests.delete(path, custom_headers) + r.raise_for_status() + + @staticmethod + def get_members(server_id): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token(), 'accept':'application/json'} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/members" + r = requests.get(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def get_user_id(server_id, username): + all_members = DiscordAPIManager.get_members(server_id) + for member in all_members: + if member['user']['username'] == username: + return member['user']['id'] + raise KeyError('User not found on server: ' + username) + + @staticmethod + def get_roles(server_id): + custom_headers = {'authorization': DiscordAPIManager.get_auth_token(), 'accept':'application/json'} + path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles" + r = requests.get(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def get_group_id(server_id, group_name): + all_roles = DiscordAPIManager.get_roles(server_id) + for role in all_roles: + if role['name'] == group_name: + return role['id'] + raise KeyError('Group not found on server: ' + group_name) class DiscordManager: - def __init__(self, discord_client): - self.discord_client = discord_client - discord_client.client.run() - super().__init__() + def __init__(self): + pass + + @staticmethod + def __sanatize_username(username): + clean = re.sub(r'[^\w]','_', username) + return clean + + @staticmethod + def add_user(username): + try: + username_clean = DiscordManager.__sanatize_username(username) + invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] + DiscordAPIManager.register_user(settings.DISCORD_SERVER_ID, username_clean, invite_code) + user_id = DiscordAPIManager.get_user_id(username_clean) + return username_clean, user_id + except: + return "", "" + + @staticmethod + def delete_user(username): + try: + DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, username) + return True + except: + return False + + @staticmethod + def update_groups(username, groups): + user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username) + group_ids = [] + for g in groups: + try: + group_id = DiscordAPIManager.get_group_id(settings.DISCORD_SERVER_ID, g.name) + group_ids.append(group_id) + except: + # need to create role on server for group + group_ids.append(DiscordManager.create_group(g.name)) + DiscordAPIManager.set_roles(settings.DISCORD_SERVER_ID, user_id, group_ids) + + @staticmethod + def create_group(groupname): + safe_groupname = DiscordManager.__sanatize_username(groupname) + new_group = DiscordAPIManager.generate_role(settings.DISCORD_SERVER_ID) + named_group = DiscordAPIManager.edit_role(settings.DISCORD_SERVER_ID, new_group['id'], safe_groupname) + return named_group['id'] + + @staticmethod + def lock_user(username): + user_id = DiscordAPIManager.get_user_id(username) + DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) + + @staticmethod + def unlock_user(username): + user_id = DiscordAPIManager.get_user_id(username) + DiscordAPIManager.unban_user(settings.DISCORD_SERVER_ID, user_id) diff --git a/services/managers/util/discord_api_manager.py b/services/managers/util/discord_api_manager.py deleted file mode 100644 index 0adfcdb2..00000000 --- a/services/managers/util/discord_api_manager.py +++ /dev/null @@ -1,138 +0,0 @@ -import requests -import json -from django.conf import settings - -DISCORD_URL = "https://discordapp.com/api" - -class DiscordManager: - - def __init__(self): - pass - - @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)) - r.raise_for_status() - return r.json()['token'] - - @staticmethod - def add_server(name): - data = {"name": name} - custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds" - r = requests.post(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - return r.json() - - @staticmethod - def rename_server(server_id, name): - data = {"name": name} - custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - return r.json() - - @staticmethod - def delete_server(server_id): - custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) - r = requests.delete(path, headers=custom_headers) - r.raise_for_status() - - @staticmethod - def get_members(server_id): - custom_headers = {'accept':'application/json', 'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/members" - r = requests.get(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - @staticmethod - def get_bans(server_id): - custom_headers = {'accept':'application/json', 'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans" - r = requests.get(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - @staticmethod - def ban_user(server_id, user_id, delete_message_age=0): - custom_headers = {'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) + "?delete-message-days=" + str(delete_message_age) - r = requests.put(path, headers=custom_headers) - r.raise_for_status() - - @staticmethod - def unban_user(server_id, user_id): - custom_headers = {'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) - r = requests.delete(path, headers=custom_headers) - r.raise_for_status() - - @staticmethod - def generate_role(server_id): - custom_headers = {'accept':'application/json', 'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles" - r = requests.post(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - @staticmethod - def edit_role(server_id, role_id, name, color=0, hoist=True, permissions=36953089): - custom_headers = {'content-type':'application/json', 'authorization': DiscordManager.get_auth_token()} - data = { - 'color': color, - 'hoist': hoist, - 'name': name, - 'permissions': permissions, - } - path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles/" + str(role_id) - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - return r.json() - - - @staticmethod - def delete_role(server_id, role_id): - custom_headers = {'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(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() - - @staticmethod - def accept_invite(invite_id): - custom_headers = {'accept': 'application/json'} - path = DISCORD_URL + "/invite/" + str(invite_id) - r = requests.post(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - @staticmethod - def create_invite(channel_id): - custom_headers = {'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/channels/" + str(channel_id) + "/invites" - r = requests.post(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - @staticmethod - def delete_invite(invite_id): - custom_headers = {'authorization': DiscordManager.get_auth_token()} - path = DISCORD_URL + "/invite/" + str(invite_id) - r = requests.delete(path, headers=custom_headers) - r.raise_for_status() From 765fcb52ded113d43b308c6f39ea7cea49ede3aa Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 21:53:49 +0000 Subject: [PATCH 04/30] Added required settings to example settings.py Added additional fields in authserviceinfos to represent username and uid --- alliance_auth/settings.py.example | 11 +++++++++++ authentication/models.py | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index c4c38b17..15ee3829 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -330,3 +330,14 @@ TEAMSPEAK3_SERVERQUERY_USER = os.environ.get('AA_TEAMSPEAK3_SERVERQUERY_USER', ' TEAMSPEAK3_SERVERQUERY_PASSWORD = os.environ.get('AA_TEAMSPEAK3_SERVERQUERY_PASSWORD', 'passwordhere') TEAMSPEAK3_VIRTUAL_SERVER = int(os.environ.get('AA_TEAMSPEAK3_VIRTUAL_SERVER', '1')) TEAMSPEAK3_PUBLIC_URL = os.environ.get('AA_TEAMSPEAK3_PUBLIC_URL', 'yourdomain.com') + +###################################### +# Discord Configuration +###################################### +# DISCORD_SERVER_ID - ID of the server to manage +# DISCORD_USER_EMAIL - email of the server management user +# DISCORD_USER_PASSWORD - password of the server management user +###################################### +DISCORD_SERVER_ID = os.environ.get('AA_DISCORD_SERVER_ID', '') +DISCORD_USER_EMAIL = os.environ.get('AA_DISCORD_USER_EMAIL', '') +DISCORD_USER_PASSWORD = os.environ.get('AA_DISCORD_USER_PASSWORD', '') diff --git a/authentication/models.py b/authentication/models.py index 2b8cfd2d..a6c983ef 100755 --- a/authentication/models.py +++ b/authentication/models.py @@ -13,9 +13,11 @@ class AuthServicesInfo(models.Model): mumble_password = models.CharField(max_length=254, default="") teamspeak3_uid = models.CharField(max_length=254, default="") teamspeak3_perm_key = models.CharField(max_length=254, default="") + discord_username = models.CharField(max_length=254, default="") + discord_uid = models.CharField(max_length=254, default="") main_char_id = models.CharField(max_length=64, default="") is_blue = models.BooleanField(default=False) user = models.ForeignKey(User) def __str__(self): - return self.user.username + ' - AuthInfo' \ No newline at end of file + return self.user.username + ' - AuthInfo' From 34a27ba885a09178b270b57e4c014b37d2ae6e49 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 22:08:17 +0000 Subject: [PATCH 05/30] Added syncgroup logic to celery tasks. Wrote request handles for enabling and disabling discord user. --- authentication/managers.py | 7 +++++++ celerytask/tasks.py | 18 ++++++++++++++++++ services/managers/discord_manager.py | 7 +++---- services/views.py | 27 +++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/authentication/managers.py b/authentication/managers.py index cee8b1f9..9b2bfb49 100755 --- a/authentication/managers.py +++ b/authentication/managers.py @@ -80,3 +80,10 @@ class AuthServicesInfoManager: authserviceinfo.is_blue = is_blue authserviceinfo.save(update_fields=['is_blue']) + @staticmethod + def update_user_discord_info(username, user_id, user): + if User.objects.filter(username=user.username).exists(): + authserviceinfo = AuthServicesInfoManager.__get_or_create(user) + authserviceinfo.discord_username = username + authserviceinfo.discord_uid = user_id + authserviceinfo.save(update_fields=['discord_username', 'discord_uid']) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index a8f3db71..154e1d5c 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -9,6 +9,7 @@ from services.managers.mumble_manager import MumbleManager from services.managers.phpbb3_manager import Phpbb3Manager from services.managers.ipboard_manager import IPBoardManager from services.managers.teamspeak3_manager import Teamspeak3Manager +from services.managers.discord_manager import DiscordManager from services.models import AuthTS from services.models import TSgroup from authentication.models import AuthServicesInfo @@ -105,6 +106,17 @@ def update_teamspeak3_groups(user): Teamspeak3Manager.update_groups(authserviceinfo.teamspeak3_uid, groups) +def update_discord_groups(user): + syncgroups = SyncGroupCache.objects.filter(user=user) + authserviceinfo = AuthServicesInfo.objects.get(user=user) + groups = [] + for syncgroup in syncgroups: + groups.append(str(syncgroup.groupname)) + + if len(groups) == 0: + groups.append('empty') + + DiscordManager.update_groups(authserviceinfo.discord_username, groups) def create_syncgroup_for_user(user, groupname, servicename): synccache = SyncGroupCache() @@ -151,6 +163,10 @@ def add_to_databases(user, groups, syncgroups): if syncgroups.filter(groupname=group.name).filter(servicename="ipboard").exists() is not True: create_syncgroup_for_user(user, group.name, "ipboard") update_ipboard_groups(user) + if authserviceinfo.discord_username and authserviceinfo.discord_username != "": + if syncgroups.filter(groupname=group.name).filter(servicename="discord").exists() is not True: + create_syncgroup_for_user(user, group.name, "discord") + update_discord_groups(user) def remove_from_databases(user, groups, syncgroups): @@ -180,6 +196,8 @@ def remove_from_databases(user, groups, syncgroups): update_ipboard_groups(user) if authserviceinfo.teamspeak3_uid and authserviceinfo.teamspeak3_uid != "": update_teamspeak3_groups(user) + if authserviceinfo.discord_username and authserviceinfo.discord_username != "": + update_discord_groups(user) # Run every minute diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index b08dcde7..d957052f 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -237,18 +237,17 @@ class DiscordManager: group_ids = [] for g in groups: try: - group_id = DiscordAPIManager.get_group_id(settings.DISCORD_SERVER_ID, g.name) + group_id = DiscordAPIManager.get_group_id(settings.DISCORD_SERVER_ID, g) group_ids.append(group_id) except: # need to create role on server for group - group_ids.append(DiscordManager.create_group(g.name)) + group_ids.append(DiscordManager.create_group(g)) DiscordAPIManager.set_roles(settings.DISCORD_SERVER_ID, user_id, group_ids) @staticmethod def create_group(groupname): - safe_groupname = DiscordManager.__sanatize_username(groupname) new_group = DiscordAPIManager.generate_role(settings.DISCORD_SERVER_ID) - named_group = DiscordAPIManager.edit_role(settings.DISCORD_SERVER_ID, new_group['id'], safe_groupname) + named_group = DiscordAPIManager.edit_role(settings.DISCORD_SERVER_ID, new_group['id'], groupname) return named_group['id'] @staticmethod diff --git a/services/views.py b/services/views.py index f0ba185b..ca1885bd 100755 --- a/services/views.py +++ b/services/views.py @@ -12,6 +12,7 @@ from managers.phpbb3_manager import Phpbb3Manager from managers.mumble_manager import MumbleManager from managers.ipboard_manager import IPBoardManager from managers.teamspeak3_manager import Teamspeak3Manager +from managers.discord_manager import DiscordManager from authentication.managers import AuthServicesInfoManager from eveonline.managers import EveManager from celerytask.tasks import remove_all_syncgroups_for_service @@ -317,3 +318,29 @@ def fleet_fits(request): context = {} return render_to_response('registered/fleetfits.html', context, context_instance=RequestContext(request)) + +@login_required +@user_passes_test(service_blue_alliance_test) +def activate_discord(request): + authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + character = EveManager.get_character_by_id(authinfo.main_char_id) + info = DiscordManager.add_user(character.character_name) + # If our username is blank means we already had a user + if info[0] is not "": + AuthServicesInfoManager.update_user_discord_info(info[0], info[1], request.user) + update_discord_groups(request.user) + return HttpResponseRedirect("/services/") + return HttpResponseRedirect("/dashboard") + +@login_required +@user_passes_test(service_blue_alliance_test) +def deactivate_discord(request): + authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + result = DiscordManager.delete_user(authinfo.jabber_username) + remove_all_syncgroups_for_service(request.user, "discord") + # If our username is blank means we failed + if result: + AuthServicesInfoManager.update_user_discord_info("", "", request.user) + return HttpResponseRedirect("/services/") + return HttpResponseRedirect("/dashboard") + From 2da93d4410b7a99be7d3a86d06ea583010197e68 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 22:30:18 +0000 Subject: [PATCH 06/30] Added required settings and context to render services page. Added URLs for enabling and disabling Discord. Added Discord section to services page. --- alliance_auth/settings.py.example | 12 ++++-- alliance_auth/urls.py | 4 ++ stock/templates/registered/services.html | 52 ++++++++++++++++++++++++ util/context_processors.py | 2 + 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 15ee3829..5719ba82 100755 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -202,12 +202,14 @@ DEFAULT_BLUE_GROUP = os.environ.get('AA_DEFAULT_BLUE_GROUP', 'Blue') # ENABLE_AUTH_JABBER - Enable jabber support in the auth for auth'd members # ENABLE_AUTH_MUMBLE - Enable mumble support in the auth for auth'd members # ENABLE_AUTH_IPBOARD - Enable IPBoard forum support in the auth for auth'd members +# ENABLE_AUTH_DISCORD - Enable Discord support in the auth for auth'd members ######################### -ENABLE_AUTH_FORUM = 'True' == os.environ.get('AA_ENABLE_AUTH_FORUM', 'True') -ENABLE_AUTH_JABBER = 'True' == os.environ.get('AA_ENABLE_AUTH_JABBER', 'True') -ENABLE_AUTH_MUMBLE = 'True' == os.environ.get('AA_ENABLE_AUTH_MUMBLE', 'True') +ENABLE_AUTH_FORUM = 'True' == os.environ.get('AA_ENABLE_AUTH_FORUM', 'False') +ENABLE_AUTH_JABBER = 'True' == os.environ.get('AA_ENABLE_AUTH_JABBER', 'False') +ENABLE_AUTH_MUMBLE = 'True' == os.environ.get('AA_ENABLE_AUTH_MUMBLE', 'False') ENABLE_AUTH_IPBOARD = 'True' == os.environ.get('AA_ENABLE_AUTH_IPBOARD', 'False') ENABLE_AUTH_TEAMSPEAK3 = 'True' == os.environ.get('AA_ENABLE_AUTH_TEAMSPEAK3', 'False') +ENABLE_AUTH_DISCORD = 'True' == os.environ.get('AA_ENABLE_AUTH_DISCORD', 'False') ##################### # Blue service Setup @@ -217,13 +219,15 @@ ENABLE_AUTH_TEAMSPEAK3 = 'True' == os.environ.get('AA_ENABLE_AUTH_TEAMSPEAK3', ' # ENABLE_BLUE_JABBER - Enable jabber support in the auth for blues # ENABLE_BLUE_MUMBLE - Enable mumble support in the auth for blues # ENABLE_BLUE_IPBOARD - Enable IPBoard forum support in the auth for blues +# ENABLE_BLUE_DISCORD - Enable Discord support in the auth for blues ##################### BLUE_STANDING = float(os.environ.get('AA_BLUE_STANDING', '5.0')) ENABLE_BLUE_FORUM = 'True' == os.environ.get('AA_ENABLE_BLUE_FORUM', 'False') ENABLE_BLUE_JABBER = 'True' == os.environ.get('AA_ENABLE_BLUE_JABBER', 'False') -ENABLE_BLUE_MUMBLE = 'True' == os.environ.get('AA_ENABLE_BLUE_MUMBLE', 'True') +ENABLE_BLUE_MUMBLE = 'True' == os.environ.get('AA_ENABLE_BLUE_MUMBLE', 'False') ENABLE_BLUE_IPBOARD = 'True' == os.environ.get('AA_ENABLE_BLUE_IPBOARD', 'False') ENABLE_BLUE_TEAMSPEAK3 = 'True' == os.environ.get('AA_ENABLE_BLUE_TEAMSPEAK3', 'False') +ENABLE_BLUE_DISCORD = 'True' == os.environ.get('AA_ENABLE_BLUE_DISCORD', 'False') ######################### # Corp Configuration diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 21758bf9..dbdbb767 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -125,6 +125,10 @@ urlpatterns = patterns('', url(r'reset_teamspeak3_perm/$', 'services.views.reset_teamspeak3_perm', name='auth_reset_teamspeak3_perm'), + # Discord Service Control + url(r'^activate_discord/$', 'services.views.activate_discord', name='auth_activate_discord'), + url(r'^deactivate_discord/$', 'services.views.deactivate_discord', name='auth_deactivate_discord'), + # Tools url(r'^tool/fleet_formatter_tool/$', 'services.views.fleet_formatter_view', name='auth_fleet_format_tool_view'), diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 81935390..5de97501 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -152,6 +152,32 @@ {% endif %} + {% if ENABLE_BLUE_DISCORD %} + + Service + Username + User ID + Action + + + Discord + {{ authinfo.discord_username }} + {{ authinfo.discord_uid }} + + {% ifequal authinfo.discord_username "" %} + + + + {% else %} + + + + {% endifequal %} + + + {% endif %} {% elif perms.auth.member %} @@ -298,6 +324,32 @@ {% endif %} + {% if ENABLE_AUTH_DISCORD %} + + + + + + + + + + + + + {% endif %}
ServiceUsernameUser IDAction
Discord{{ authinfo.discord_username }}{{ authinfo.discord_uid }} + {% ifequal authinfo.discord_username "" %} + + + + {% else %} + + + + {% endifequal %} +
{% else %} {% if IS_CORP %} diff --git a/util/context_processors.py b/util/context_processors.py index 245c023e..b055737b 100755 --- a/util/context_processors.py +++ b/util/context_processors.py @@ -34,11 +34,13 @@ def domain_url(request): 'ENABLE_AUTH_MUMBLE': settings.ENABLE_AUTH_MUMBLE, 'ENABLE_AUTH_IPBOARD': settings.ENABLE_AUTH_IPBOARD, 'ENABLE_AUTH_TEAMSPEAK3': settings.ENABLE_AUTH_TEAMSPEAK3, + 'ENABLE_AUTH_DISCORD': settings.ENABLE_AUTH_DISCORD, 'ENABLE_BLUE_JABBER': settings.ENABLE_BLUE_JABBER, 'ENABLE_BLUE_FORUM': settings.ENABLE_BLUE_FORUM, 'ENABLE_BLUE_MUMBLE': settings.ENABLE_BLUE_MUMBLE, 'ENABLE_BLUE_IPBOARD': settings.ENABLE_BLUE_IPBOARD, 'ENABLE_BLUE_TEAMSPEAK3': settings.ENABLE_BLUE_TEAMSPEAK3, + 'ENABLE_BLUE_DISCORD': settings.ENABLE_BLUE_DISCORD, 'TEAMSPEAK3_PUBLIC_URL': settings.TEAMSPEAK3_PUBLIC_URL, 'JACK_KNIFE_URL': settings.JACK_KNIFE_URL, 'CURRENT_UTC_TIME': timezone.now()} From a6447d359608491ef5e2825e90661652a9a95db8 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 23:01:44 +0000 Subject: [PATCH 07/30] Added link to discord server to services page. Corrected handling of user deletion to return true if account absent on server. --- services/managers/discord_manager.py | 11 ++++++++--- services/views.py | 1 + stock/templates/registered/services.html | 4 ++++ util/context_processors.py | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index d957052f..d0f61016 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -168,7 +168,7 @@ class DiscordAPIManager: def kick_user(server_id, user_id): custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} path = DISCORD_URL + "/guilds/" + str(server_id) + "/members/" + str(user_id) - r = requests.delete(path, custom_headers) + r = requests.delete(path, headers=custom_headers) r.raise_for_status() @staticmethod @@ -218,7 +218,7 @@ class DiscordManager: username_clean = DiscordManager.__sanatize_username(username) invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] DiscordAPIManager.register_user(settings.DISCORD_SERVER_ID, username_clean, invite_code) - user_id = DiscordAPIManager.get_user_id(username_clean) + user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username_clean) return username_clean, user_id except: return "", "" @@ -226,7 +226,12 @@ class DiscordManager: @staticmethod def delete_user(username): try: - DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, username) + user_id = DiscordAPIManager.get_user_id(username) + except: + #user does not exist + return True + try: + DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, user_id) return True except: return False diff --git a/services/views.py b/services/views.py index ca1885bd..a566fe63 100755 --- a/services/views.py +++ b/services/views.py @@ -21,6 +21,7 @@ from celerytask.tasks import update_mumble_groups from celerytask.tasks import update_forum_groups from celerytask.tasks import update_ipboard_groups from celerytask.tasks import update_teamspeak3_groups +from celerytask.tasks import update_discord_groups from forms import JabberBroadcastForm from forms import FleetFormatterForm from util import check_if_user_has_permission diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 5de97501..c26b5ced 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -157,12 +157,14 @@ Service Username User ID + Domain Action Discord {{ authinfo.discord_username }} {{ authinfo.discord_uid }} + https://discordapp.com {% ifequal authinfo.discord_username "" %} @@ -329,12 +331,14 @@ Service Username User ID + Domain Action Discord {{ authinfo.discord_username }} {{ authinfo.discord_uid }} + https://discordapp.com {% ifequal authinfo.discord_username "" %} diff --git a/util/context_processors.py b/util/context_processors.py index b055737b..3ddbbe92 100755 --- a/util/context_processors.py +++ b/util/context_processors.py @@ -43,4 +43,5 @@ def domain_url(request): 'ENABLE_BLUE_DISCORD': settings.ENABLE_BLUE_DISCORD, 'TEAMSPEAK3_PUBLIC_URL': settings.TEAMSPEAK3_PUBLIC_URL, 'JACK_KNIFE_URL': settings.JACK_KNIFE_URL, + 'DISCORD_SERVER_ID': settings.DISCORD_SERVER_ID, 'CURRENT_UTC_TIME': timezone.now()} From d9ffaa5e5032f28587817fac902177fb9898f87f Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 23:41:44 +0000 Subject: [PATCH 08/30] Initial work on reset discord account. --- alliance_auth/urls.py | 1 + services/managers/discord_manager.py | 7 +++---- services/views.py | 16 ++++++++++++++-- stock/templates/registered/services.html | 8 ++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index dbdbb767..78f3fbd4 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -128,6 +128,7 @@ urlpatterns = patterns('', # Discord Service Control url(r'^activate_discord/$', 'services.views.activate_discord', name='auth_activate_discord'), url(r'^deactivate_discord/$', 'services.views.deactivate_discord', name='auth_deactivate_discord'), + url(r'^reset_discord/$', 'services.views.reset_discord', name='auth_reset_discord'), # Tools url(r'^tool/fleet_formatter_tool/$', 'services.views.fleet_formatter_view', diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index d0f61016..0b99e26f 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -227,13 +227,12 @@ class DiscordManager: def delete_user(username): try: user_id = DiscordAPIManager.get_user_id(username) - except: + DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, user_id) + except KeyError: #user does not exist return True - try: - DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, user_id) - return True except: + #something went wrong return False @staticmethod diff --git a/services/views.py b/services/views.py index a566fe63..980c3f47 100755 --- a/services/views.py +++ b/services/views.py @@ -337,11 +337,23 @@ def activate_discord(request): @user_passes_test(service_blue_alliance_test) def deactivate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.delete_user(authinfo.jabber_username) + result = DiscordManager.delete_user(authinfo.discord_username) remove_all_syncgroups_for_service(request.user, "discord") - # If our username is blank means we failed if result: AuthServicesInfoManager.update_user_discord_info("", "", request.user) return HttpResponseRedirect("/services/") return HttpResponseRedirect("/dashboard") +@login_required +@user_passes_test(service_blue_alliance_test) +def reset_discord(request): + authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + result = DiscordManager.delete_user(authinfo.discord_username) + if result: + # ensures succesful deletion + new_result = DiscordManager.add_user(authinfo.discord_username) + if new_result: + # ensures succesful creation + AuthServicesInfoManager.update_user_discord_info(new_result[0], new_result[1], request.user) + return HttpResponseRedirect("/services/") + return HttpResponseRedirect("/services/") diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index c26b5ced..0a2d4d86 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -172,6 +172,10 @@ class="glyphicon glyphicon-ok"> {% else %} + + + @@ -346,6 +350,10 @@ class="glyphicon glyphicon-ok"> {% else %} + + + From d3c8189c92bfcb5a2f8186d85b014181f32d0d82 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Mon, 30 Nov 2015 23:51:39 +0000 Subject: [PATCH 09/30] Corrected Discord user deletion logic. Fixed Discord account reset. --- services/managers/discord_manager.py | 3 ++- services/views.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 0b99e26f..0851703c 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -226,8 +226,9 @@ class DiscordManager: @staticmethod def delete_user(username): try: - user_id = DiscordAPIManager.get_user_id(username) + user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username) DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, user_id) + return True except KeyError: #user does not exist return True diff --git a/services/views.py b/services/views.py index 980c3f47..b612d6ce 100755 --- a/services/views.py +++ b/services/views.py @@ -351,9 +351,11 @@ def reset_discord(request): result = DiscordManager.delete_user(authinfo.discord_username) if result: # ensures succesful deletion + AuthServicesInfoManager.update_user_discord_info("", "", request.user) new_result = DiscordManager.add_user(authinfo.discord_username) if new_result: # ensures succesful creation AuthServicesInfoManager.update_user_discord_info(new_result[0], new_result[1], request.user) + update_discord_groups(request.user) return HttpResponseRedirect("/services/") return HttpResponseRedirect("/services/") From 7001071820317a8fbcc1a16b79e15910830812e0 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 00:27:59 +0000 Subject: [PATCH 10/30] Deleted unnecessary discord client. --- services/managers/util/discord_client.py | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 services/managers/util/discord_client.py diff --git a/services/managers/util/discord_client.py b/services/managers/util/discord_client.py deleted file mode 100644 index c5dd722a..00000000 --- a/services/managers/util/discord_client.py +++ /dev/null @@ -1,17 +0,0 @@ -import discord -from django.conf import settings - - -client = discord.Client() - -print('Logging in to Discord as ' + settings.DISCORD_USER_EMAIL) -client.login(settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) -if not client.is_logged_in: - print('Logging in to Discord failed') - raise ValueError('Supplied Discord credentials failed login') - -@client.event -def on_ready(): - server = client.servers[0] - user = client.user - print('Connected as ' + user.name) From 728a18b763898043b4d8351acc73d89cecaf3258 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 00:37:54 +0000 Subject: [PATCH 11/30] Corrected default invite parameters to increase security: 5 minute lifetime, 1 use. --- services/managers/discord_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 0851703c..f1318536 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -124,12 +124,12 @@ class DiscordAPIManager: return r.json() @staticmethod - def create_invite(server_id, max_age=0, max_users=1, temporary=True, xkcdpass=False): + def create_invite(server_id, max_age=600, max_uses=1, temporary=True, xkcdpass=False): custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} path = DISCORD_URL + "/channels/" + str(server_id) + "/invites" data = { 'max_age': max_age, - 'max_users': max_users, + 'max_uses': max_uses, 'temporary': temporary, 'xkcdpass': xkcdpass, } From bec690ad51235410e7f4982259769ae46ae69dee Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 00:42:04 +0000 Subject: [PATCH 12/30] Deletes invites once user registered as Discord ignores max_age right now. --- services/managers/discord_manager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index f1318536..cfccb335 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -218,7 +218,8 @@ class DiscordManager: username_clean = DiscordManager.__sanatize_username(username) invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] DiscordAPIManager.register_user(settings.DISCORD_SERVER_ID, username_clean, invite_code) - user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username_clean) + user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username_clean) + DiscordAPIManager.delete_invite(invite_code) return username_clean, user_id except: return "", "" From 90522a50534c0bec705afa89ecb45f5930386158 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 03:25:48 +0000 Subject: [PATCH 13/30] Changed default group permission to: - Read Messages - Send Messages - Embed Links - Read Message History - Connect - Speak - Use Voice Activity --- services/managers/discord_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index cfccb335..9f5ccaf3 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -86,7 +86,7 @@ class DiscordAPIManager: return r.json() @staticmethod - def edit_role(server_id, role_id, name, color=0, hoist=True, permissions=36953089): + def edit_role(server_id, role_id, name, color=0, hoist=True, permissions=36785152): custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} data = { 'color': color, From c00942053686785d3d1794502ad88da886ba39fd Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 04:12:50 +0000 Subject: [PATCH 14/30] Included Discord in disable_services from common_task. Changed how user accounts in discord are handled: endpoint accepts password and email. Accounts are created with a password(random) and their user email. Need to activate account through link in email. --- authentication/models.py | 2 +- services/managers/discord_manager.py | 16 +++-- services/views.py | 4 +- stock/templates/registered/services.html | 82 +++++++++++++++--------- util/common_task.py | 4 ++ 5 files changed, 69 insertions(+), 39 deletions(-) diff --git a/authentication/models.py b/authentication/models.py index a6c983ef..29bbbeec 100755 --- a/authentication/models.py +++ b/authentication/models.py @@ -14,7 +14,7 @@ class AuthServicesInfo(models.Model): teamspeak3_uid = models.CharField(max_length=254, default="") teamspeak3_perm_key = models.CharField(max_length=254, default="") discord_username = models.CharField(max_length=254, default="") - discord_uid = models.CharField(max_length=254, default="") + discord_password = models.CharField(max_length=254, default="") main_char_id = models.CharField(max_length=64, default="") is_blue = models.BooleanField(default=False) user = models.ForeignKey(User) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 9f5ccaf3..d8102e24 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -2,6 +2,7 @@ import requests import json from django.conf import settings import re +import os DISCORD_URL = "https://discordapp.com/api" @@ -153,12 +154,14 @@ class DiscordAPIManager: r.raise_for_status() @staticmethod - def register_user(server_id, username, invite_code): + def register_user(server_id, username, invite_code, password, email): custom_headers = {'content-type': 'application/json'} data = { 'fingerprint': None, 'username': username, 'invite': invite_code, + 'passowrd': password, + 'email': email, } path = DISCORD_URL + "/auth/register" r = requests.post(path, headers=custom_headers, data=json.dumps(data)) @@ -213,14 +216,19 @@ class DiscordManager: return clean @staticmethod - def add_user(username): + def __generate_random_pass(): + return os.urandom(8).encode('hex') + + @staticmethod + def add_user(username, email): try: username_clean = DiscordManager.__sanatize_username(username) invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] - DiscordAPIManager.register_user(settings.DISCORD_SERVER_ID, username_clean, invite_code) + password = DiscordManager.__generate_random_pass() + DiscordAPIManager.register_user(server_id=settings.DISCORD_SERVER_ID, username=username_clean, invite=invite_code, password=password, email=email) user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username_clean) DiscordAPIManager.delete_invite(invite_code) - return username_clean, user_id + return username_clean, password except: return "", "" diff --git a/services/views.py b/services/views.py index b612d6ce..100f05b5 100755 --- a/services/views.py +++ b/services/views.py @@ -325,7 +325,7 @@ context_instance=RequestContext(request)) def activate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) character = EveManager.get_character_by_id(authinfo.main_char_id) - info = DiscordManager.add_user(character.character_name) + info = DiscordManager.add_user(character.character_name, request.user.email) # If our username is blank means we already had a user if info[0] is not "": AuthServicesInfoManager.update_user_discord_info(info[0], info[1], request.user) @@ -352,7 +352,7 @@ def reset_discord(request): if result: # ensures succesful deletion AuthServicesInfoManager.update_user_discord_info("", "", request.user) - new_result = DiscordManager.add_user(authinfo.discord_username) + new_result = DiscordManager.add_user(authinfo.discord_username, request.user.email) if new_result: # ensures succesful creation AuthServicesInfoManager.update_user_discord_info(new_result[0], new_result[1], request.user) diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 0a2d4d86..85837823 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -114,6 +114,31 @@ {% endif %} + {% if ENABLE_BLUE_DISCORD %} + + Discord + {{ authinfo.discord_username }} + {{ authinfo.discord_password }} + https://discordapp.com + + {% ifequal authinfo.discord_username "" %} + + + + {% else %} + + + + + + + {% endifequal %} + + + {% endif %} {% if ENABLE_BLUE_TEAMSPEAK3 %} Service @@ -152,38 +177,6 @@ {% endif %} - {% if ENABLE_BLUE_DISCORD %} - - Service - Username - User ID - Domain - Action - - - Discord - {{ authinfo.discord_username }} - {{ authinfo.discord_uid }} - https://discordapp.com - - {% ifequal authinfo.discord_username "" %} - - - - {% else %} - - - - - - - {% endifequal %} - - - {% endif %} {% elif perms.auth.member %} @@ -292,6 +285,31 @@ {% endif %} + {% if ENABLE_AUTH_DISCORD %} + + + + + + + + {% endif %} {% if ENABLE_AUTH_TEAMSPEAK3 %} diff --git a/util/common_task.py b/util/common_task.py index 5c613447..dc7bf364 100755 --- a/util/common_task.py +++ b/util/common_task.py @@ -7,6 +7,7 @@ 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 DiscordManager def add_user_to_group(user, groupname): @@ -41,6 +42,9 @@ def deactivate_services(user): if authinfo.teamspeak3_uid and authinfo.teamspeak3_uid != "": Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) AuthServicesInfoManager.update_user_teamspeak3_info("", "", user) + if authinfo.discord_username and authinfo.discord_username != "": + DiscordManager.delete_user(authinfo.discord_username) + AuthServicesInfoManager.update_user_discord_info("", "", user) def generate_corp_group_name(corpname): From 4ac7c4249cbad610827f3ed892142c8e23d26e33 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 04:15:43 +0000 Subject: [PATCH 15/30] Updated AuthServiceInfoManager to update correct fields. --- authentication/managers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/authentication/managers.py b/authentication/managers.py index 9b2bfb49..26d2cdd8 100755 --- a/authentication/managers.py +++ b/authentication/managers.py @@ -81,9 +81,9 @@ class AuthServicesInfoManager: authserviceinfo.save(update_fields=['is_blue']) @staticmethod - def update_user_discord_info(username, user_id, user): + def update_user_discord_info(username, password, user): if User.objects.filter(username=user.username).exists(): authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo.discord_username = username - authserviceinfo.discord_uid = user_id - authserviceinfo.save(update_fields=['discord_username', 'discord_uid']) + authserviceinfo.discord_password = password + authserviceinfo.save(update_fields=['discord_username', 'discord_password']) From 45e91f3b1f9d59444e7ec855f4cf4b38cfffbf55 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 04:26:18 +0000 Subject: [PATCH 16/30] Removed duplicate entry of discord row in services list. --- stock/templates/registered/services.html | 32 ------------------------ 1 file changed, 32 deletions(-) diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 85837823..0f65ed09 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -348,38 +348,6 @@ {% endif %} - {% if ENABLE_AUTH_DISCORD %} - - - - - - - - - - - - - - - {% endif %}
Discord{{ authinfo.discord_username }}{{ authinfo.discord_password }}https://discordapp.com + {% ifequal authinfo.discord_username "" %} + + + + {% else %} + + + + + + + {% endifequal %} +
Service
ServiceUsernameUser IDDomainAction
Discord{{ authinfo.discord_username }}{{ authinfo.discord_uid }}https://discordapp.com - {% ifequal authinfo.discord_username "" %} - - - - {% else %} - - - - - - - {% endifequal %} -
{% else %} {% if IS_CORP %} From 7461501d413c755f6ab67744b2a218a1f078a82e Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 04:28:17 +0000 Subject: [PATCH 17/30] Corrected parameter list for user registration. --- services/managers/discord_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index d8102e24..9ae5ceb3 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -225,7 +225,7 @@ class DiscordManager: username_clean = DiscordManager.__sanatize_username(username) invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] password = DiscordManager.__generate_random_pass() - DiscordAPIManager.register_user(server_id=settings.DISCORD_SERVER_ID, username=username_clean, invite=invite_code, password=password, email=email) + DiscordAPIManager.register_user(server_id=settings.DISCORD_SERVER_ID, username=username_clean, invite_code=invite_code, password=password, email=email) user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username_clean) DiscordAPIManager.delete_invite(invite_code) return username_clean, password From 54d216bdf0a6fb689af27c83f513977d07f0a2bb Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 04:50:14 +0000 Subject: [PATCH 18/30] Changed how user account deletions are handled. Now bans/unbans account as necessary. --- services/managers/discord_manager.py | 16 ++++++++++++---- services/views.py | 17 +++++------------ util/common_task.py | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 9ae5ceb3..b5627e17 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -266,10 +266,18 @@ class DiscordManager: @staticmethod def lock_user(username): - user_id = DiscordAPIManager.get_user_id(username) - DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) + try: + user_id = DiscordAPIManager.get_user_id(username) + DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) + return True + except: + return False @staticmethod def unlock_user(username): - user_id = DiscordAPIManager.get_user_id(username) - DiscordAPIManager.unban_user(settings.DISCORD_SERVER_ID, user_id) + try: + user_id = DiscordAPIManager.get_user_id(username) + DiscordAPIManager.unban_user(settings.DISCORD_SERVER_ID, user_id) + return True + except: + return False diff --git a/services/views.py b/services/views.py index 100f05b5..114f5f1a 100755 --- a/services/views.py +++ b/services/views.py @@ -337,10 +337,9 @@ def activate_discord(request): @user_passes_test(service_blue_alliance_test) def deactivate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.delete_user(authinfo.discord_username) + result = DiscordManager.lock_user(authinfo.discord_username) remove_all_syncgroups_for_service(request.user, "discord") if result: - AuthServicesInfoManager.update_user_discord_info("", "", request.user) return HttpResponseRedirect("/services/") return HttpResponseRedirect("/dashboard") @@ -348,14 +347,8 @@ def deactivate_discord(request): @user_passes_test(service_blue_alliance_test) def reset_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.delete_user(authinfo.discord_username) + result = DiscordManager.unlock_user(authinfo.discord_username) + update_discord_groups(request.user) if result: - # ensures succesful deletion - AuthServicesInfoManager.update_user_discord_info("", "", request.user) - new_result = DiscordManager.add_user(authinfo.discord_username, request.user.email) - if new_result: - # ensures succesful creation - AuthServicesInfoManager.update_user_discord_info(new_result[0], new_result[1], request.user) - update_discord_groups(request.user) - return HttpResponseRedirect("/services/") - return HttpResponseRedirect("/services/") + return HttpResponseRedirect("/services/") + return HttpResponseRedirect("/dashboard/") diff --git a/util/common_task.py b/util/common_task.py index dc7bf364..eb61672e 100755 --- a/util/common_task.py +++ b/util/common_task.py @@ -43,7 +43,7 @@ def deactivate_services(user): Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) AuthServicesInfoManager.update_user_teamspeak3_info("", "", user) if authinfo.discord_username and authinfo.discord_username != "": - DiscordManager.delete_user(authinfo.discord_username) + DiscordManager.lock_user(authinfo.discord_username) AuthServicesInfoManager.update_user_discord_info("", "", user) From 9e72422639ab42faf99800c7dffd630ee09081b7 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 06:13:06 +0000 Subject: [PATCH 19/30] Corrected typo in register_user function preventing succesful registration. --- services/managers/discord_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index b5627e17..a6405284 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -160,7 +160,7 @@ class DiscordAPIManager: 'fingerprint': None, 'username': username, 'invite': invite_code, - 'passowrd': password, + 'password': password, 'email': email, } path = DISCORD_URL + "/auth/register" From 57b44620cdc38fc602f472c8f65659fff816c746 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 06:23:18 +0000 Subject: [PATCH 20/30] Disabled Discord account reset until a proper mechanism can be thought up. --- alliance_auth/urls.py | 2 +- services/views.py | 17 ++++++++++++----- stock/templates/registered/services.html | 8 -------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 78f3fbd4..9fb00a5d 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -128,7 +128,7 @@ urlpatterns = patterns('', # Discord Service Control url(r'^activate_discord/$', 'services.views.activate_discord', name='auth_activate_discord'), url(r'^deactivate_discord/$', 'services.views.deactivate_discord', name='auth_deactivate_discord'), - url(r'^reset_discord/$', 'services.views.reset_discord', name='auth_reset_discord'), +# url(r'^reset_discord/$', 'services.views.reset_discord', name='auth_reset_discord'), # Tools url(r'^tool/fleet_formatter_tool/$', 'services.views.fleet_formatter_view', diff --git a/services/views.py b/services/views.py index 114f5f1a..100f05b5 100755 --- a/services/views.py +++ b/services/views.py @@ -337,9 +337,10 @@ def activate_discord(request): @user_passes_test(service_blue_alliance_test) def deactivate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.lock_user(authinfo.discord_username) + result = DiscordManager.delete_user(authinfo.discord_username) remove_all_syncgroups_for_service(request.user, "discord") if result: + AuthServicesInfoManager.update_user_discord_info("", "", request.user) return HttpResponseRedirect("/services/") return HttpResponseRedirect("/dashboard") @@ -347,8 +348,14 @@ def deactivate_discord(request): @user_passes_test(service_blue_alliance_test) def reset_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.unlock_user(authinfo.discord_username) - update_discord_groups(request.user) + result = DiscordManager.delete_user(authinfo.discord_username) if result: - return HttpResponseRedirect("/services/") - return HttpResponseRedirect("/dashboard/") + # ensures succesful deletion + AuthServicesInfoManager.update_user_discord_info("", "", request.user) + new_result = DiscordManager.add_user(authinfo.discord_username, request.user.email) + if new_result: + # ensures succesful creation + AuthServicesInfoManager.update_user_discord_info(new_result[0], new_result[1], request.user) + update_discord_groups(request.user) + return HttpResponseRedirect("/services/") + return HttpResponseRedirect("/services/") diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 0f65ed09..3977eb42 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -127,10 +127,6 @@ class="glyphicon glyphicon-ok"> {% else %} - - - @@ -298,10 +294,6 @@ class="glyphicon glyphicon-ok"> {% else %} - - - From f6ef741e63c7c7c5234a579d03b44595c1e50822 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 06:55:33 +0000 Subject: [PATCH 21/30] Added password change function as reset action. --- alliance_auth/urls.py | 2 +- services/managers/discord_manager.py | 48 ++++++++++++++++++++++++ services/views.py | 13 ++----- stock/templates/registered/services.html | 8 ++++ 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 9fb00a5d..78f3fbd4 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -128,7 +128,7 @@ urlpatterns = patterns('', # Discord Service Control url(r'^activate_discord/$', 'services.views.activate_discord', name='auth_activate_discord'), url(r'^deactivate_discord/$', 'services.views.deactivate_discord', name='auth_deactivate_discord'), -# url(r'^reset_discord/$', 'services.views.reset_discord', name='auth_reset_discord'), + url(r'^reset_discord/$', 'services.views.reset_discord', name='auth_reset_discord'), # Tools url(r'^tool/fleet_formatter_tool/$', 'services.views.fleet_formatter_view', diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index a6405284..997c53c0 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -206,6 +206,45 @@ class DiscordAPIManager: return role['id'] raise KeyError('Group not found on server: ' + group_name) + @staticmethod + def get_token_by_user(email, 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)) + r.raise_for_status() + return r.json()['token'] + + @staticmethod + def get_user_profile(email, password): + token = DiscordAPIManager.get_token_by_user(email, password) + custom_headers = {'accept': 'application/json', 'authorization': token} + path = DISCORD_URL + "/users/@me" + r = requests.get(path, headers=custom_headers) + r.raise_for_status() + return r.json() + + @staticmethod + def set_user_password(email, current_password, new_password): + profile = DiscordAPIManager.get_user_profile(email, current_password) + 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() + class DiscordManager: def __init__(self): pass @@ -281,3 +320,12 @@ class DiscordManager: return True except: return False + + @staticmethod + def update_user_password(email, current_password): + new_password = DiscordManager.__generate_random_pass() + try: + profile = DiscordAPIManager.set_user_password(email, current_password, new_password) + return new_password + except: + return current_password diff --git a/services/views.py b/services/views.py index 100f05b5..08658757 100755 --- a/services/views.py +++ b/services/views.py @@ -348,14 +348,9 @@ def deactivate_discord(request): @user_passes_test(service_blue_alliance_test) def reset_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.delete_user(authinfo.discord_username) + result = DiscordManager.update_user_password(request.user.email, authinfo.discord_password) if result: - # ensures succesful deletion - AuthServicesInfoManager.update_user_discord_info("", "", request.user) - new_result = DiscordManager.add_user(authinfo.discord_username, request.user.email) - if new_result: - # ensures succesful creation - AuthServicesInfoManager.update_user_discord_info(new_result[0], new_result[1], request.user) - update_discord_groups(request.user) - return HttpResponseRedirect("/services/") + AuthServicesInfoManager.update_user_discord_info(authinfo.discord_username, result, request.user) + update_discord_groups(request.user) + return HttpResponseRedirect("/services/") return HttpResponseRedirect("/services/") diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 3977eb42..0f65ed09 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -127,6 +127,10 @@ class="glyphicon glyphicon-ok"> {% else %} + + + @@ -294,6 +298,10 @@ class="glyphicon glyphicon-ok"> {% else %} + + + From ec1b17df25549cf0ac6f1c9fa558f95024cb1300 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Tue, 1 Dec 2015 07:56:13 +0000 Subject: [PATCH 22/30] Dissociates user account from email address when deleting service. --- services/managers/discord_manager.py | 21 +++++++++++++++++---- services/views.py | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 997c53c0..d246d091 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -245,6 +245,20 @@ class DiscordAPIManager: 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() + class DiscordManager: def __init__(self): pass @@ -272,17 +286,16 @@ class DiscordManager: return "", "" @staticmethod - def delete_user(username): + def delete_user(username, email, password): try: user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username) DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, user_id) - return True - except KeyError: - #user does not exist + DiscordAPIManager.destroy_user(email, password) return True except: #something went wrong return False + return False @staticmethod def update_groups(username, groups): diff --git a/services/views.py b/services/views.py index 08658757..9def2d09 100755 --- a/services/views.py +++ b/services/views.py @@ -337,7 +337,7 @@ def activate_discord(request): @user_passes_test(service_blue_alliance_test) def deactivate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.delete_user(authinfo.discord_username) + result = DiscordManager.delete_user(authinfo.discord_username, request.user.email, authinfo.discord_password) remove_all_syncgroups_for_service(request.user, "discord") if result: AuthServicesInfoManager.update_user_discord_info("", "", request.user) From 8442ec1f5561e44602a5e77e2e3231a1dd9d3a9e Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 01:02:13 +0000 Subject: [PATCH 23/30] Changed discord account handling. Now requests email and password and grabs UID via API. UID is stored in authserviceinfo model and used as required. --- authentication/managers.py | 7 ++- authentication/models.py | 3 +- celerytask/tasks.py | 4 +- services/forms.py | 4 ++ services/managers/discord_manager.py | 55 +++++++++++++++++++----- services/views.py | 37 +++++++++++++--- stock/templates/registered/discord.html | 33 ++++++++++++++ stock/templates/registered/services.html | 12 +++--- util/common_task.py | 6 +-- 9 files changed, 127 insertions(+), 34 deletions(-) create mode 100644 stock/templates/registered/discord.html diff --git a/authentication/managers.py b/authentication/managers.py index 26d2cdd8..0cea7a07 100755 --- a/authentication/managers.py +++ b/authentication/managers.py @@ -81,9 +81,8 @@ class AuthServicesInfoManager: authserviceinfo.save(update_fields=['is_blue']) @staticmethod - def update_user_discord_info(username, password, user): + def update_user_discord_info(user_id, user): if User.objects.filter(username=user.username).exists(): authserviceinfo = AuthServicesInfoManager.__get_or_create(user) - authserviceinfo.discord_username = username - authserviceinfo.discord_password = password - authserviceinfo.save(update_fields=['discord_username', 'discord_password']) + authserviceinfo.discord_uid = user_id + authserviceinfo.save(update_fields=['discord_uid']) diff --git a/authentication/models.py b/authentication/models.py index 29bbbeec..0727e79d 100755 --- a/authentication/models.py +++ b/authentication/models.py @@ -13,8 +13,7 @@ class AuthServicesInfo(models.Model): mumble_password = models.CharField(max_length=254, default="") teamspeak3_uid = models.CharField(max_length=254, default="") teamspeak3_perm_key = models.CharField(max_length=254, default="") - discord_username = models.CharField(max_length=254, default="") - discord_password = models.CharField(max_length=254, default="") + discord_uid = models.CharField(max_length=254, default="") main_char_id = models.CharField(max_length=64, default="") is_blue = models.BooleanField(default=False) user = models.ForeignKey(User) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index 154e1d5c..af5b322c 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -116,7 +116,7 @@ def update_discord_groups(user): if len(groups) == 0: groups.append('empty') - DiscordManager.update_groups(authserviceinfo.discord_username, groups) + DiscordManager.update_groups(authserviceinfo.discord_uid, groups) def create_syncgroup_for_user(user, groupname, servicename): synccache = SyncGroupCache() @@ -196,7 +196,7 @@ def remove_from_databases(user, groups, syncgroups): update_ipboard_groups(user) if authserviceinfo.teamspeak3_uid and authserviceinfo.teamspeak3_uid != "": update_teamspeak3_groups(user) - if authserviceinfo.discord_username and authserviceinfo.discord_username != "": + if authserviceinfo.discord_uid and authserviceinfo.discord_uid != "": update_discord_groups(user) diff --git a/services/forms.py b/services/forms.py index cd322c0c..f96c404b 100644 --- a/services/forms.py +++ b/services/forms.py @@ -24,3 +24,7 @@ class FleetFormatterForm(forms.Form): 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(widget=forms.Textarea, required=False) + +class DiscordForm(forms.Form): + email = forms.CharField(label="Email Address", required=True) + password = forms.CharField(label="Password", required=True) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index d246d091..3613833a 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -117,8 +117,8 @@ class DiscordAPIManager: return r.json() @staticmethod - def accept_invite(invite_id): - custom_headers = {'accept': 'application/json'} + def accept_invite(invite_id, token): + custom_headers = {'accept': 'application/json', 'authorization': token} path = DISCORD_URL + "/invite/" + str(invite_id) r = requests.post(path, headers=custom_headers) r.raise_for_status() @@ -259,6 +259,14 @@ class DiscordAPIManager: r.raise_for_status return r.json() + @staticmethod + def check_if_user_banned(server_id, user_id): + bans = DiscordAPIManager.get_bans(server_id) + for b in bans: + if b['user']['id'] == str(user_id): + return True + return False + class DiscordManager: def __init__(self): pass @@ -273,7 +281,7 @@ class DiscordManager: return os.urandom(8).encode('hex') @staticmethod - def add_user(username, email): + def old_add_user(username, email): try: username_clean = DiscordManager.__sanatize_username(username) invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] @@ -286,7 +294,7 @@ class DiscordManager: return "", "" @staticmethod - def delete_user(username, email, password): + def old_delete_user(username, email, password): try: user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username) DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, user_id) @@ -298,8 +306,7 @@ class DiscordManager: return False @staticmethod - def update_groups(username, groups): - user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username) + def update_groups(user_id, groups): group_ids = [] for g in groups: try: @@ -317,18 +324,16 @@ class DiscordManager: return named_group['id'] @staticmethod - def lock_user(username): + def lock_user(user_id): try: - user_id = DiscordAPIManager.get_user_id(username) DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) return True except: return False @staticmethod - def unlock_user(username): + def unlock_user(user_id): try: - user_id = DiscordAPIManager.get_user_id(username) DiscordAPIManager.unban_user(settings.DISCORD_SERVER_ID, user_id) return True except: @@ -342,3 +347,33 @@ class DiscordManager: return new_password except: return current_password + + @staticmethod + def get_user_id(email, password): + try: + profile = DiscordAPIManager.get_user_profile(email, password) + return profile['user']['id'] + except: + return "" + + @staticmethod + def add_user(email, password): + try: + profile = DiscordAPIManager.get_user_profile(email, password) + user_id = profile['id'] + if DiscordAPIManager.check_if_user_banned(settings.DISCORD_SERVER_ID, user_id): + DiscordAPIManager.unban_user(settings.DISCORD_SERVER_ID, user_id) + invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] + token = DiscordAPIManager.get_token_by_user(email, password) + DiscordAPIManager.accept_invite(invite_code, token) + return user_id + except: + return "" + + @staticmethod + def delete_user(user_id): + try: + DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) + return True + except: + return False diff --git a/services/views.py b/services/views.py index 9def2d09..232c7a4b 100755 --- a/services/views.py +++ b/services/views.py @@ -24,6 +24,7 @@ from celerytask.tasks import update_teamspeak3_groups from celerytask.tasks import update_discord_groups from forms import JabberBroadcastForm from forms import FleetFormatterForm +from forms import DiscordForm from util import check_if_user_has_permission import threading @@ -322,7 +323,7 @@ context_instance=RequestContext(request)) @login_required @user_passes_test(service_blue_alliance_test) -def activate_discord(request): +def old_activate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) character = EveManager.get_character_by_id(authinfo.main_char_id) info = DiscordManager.add_user(character.character_name, request.user.email) @@ -337,10 +338,10 @@ def activate_discord(request): @user_passes_test(service_blue_alliance_test) def deactivate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.delete_user(authinfo.discord_username, request.user.email, authinfo.discord_password) + result = DiscordManager.delete_user(authinfo.discord_uid) remove_all_syncgroups_for_service(request.user, "discord") if result: - AuthServicesInfoManager.update_user_discord_info("", "", request.user) + AuthServicesInfoManager.update_user_discord_info("",request.user) return HttpResponseRedirect("/services/") return HttpResponseRedirect("/dashboard") @@ -348,9 +349,31 @@ def deactivate_discord(request): @user_passes_test(service_blue_alliance_test) def reset_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = DiscordManager.update_user_password(request.user.email, authinfo.discord_password) + result = DiscordManager.delete_user(authinfo.discord_uid) if result: - AuthServicesInfoManager.update_user_discord_info(authinfo.discord_username, result, request.user) - update_discord_groups(request.user) - return HttpResponseRedirect("/services/") + AuthServicesInfoManager.update_user_discord_info("",request.user) + return HttpResponseRedirect("/activate_discord/") return HttpResponseRedirect("/services/") + +@login_required +@user_passes_test(service_blue_alliance_test) +def activate_discord(request): + success = False + if request.method == 'POST': + form = DiscordForm(request.POST) + if form.is_valid(): + email = form.cleaned_data['email'] + password = form.cleaned_data['password'] + try: + user_id = DiscordManager.add_user(email, password) + AuthServicesInfoManager.update_user_discord_info(user_id, request.user) + update_discord_groups(request.user) + success = True + return HttpResponseRedirect("/services/") + except: + pass + else: + form = DiscordForm() + + context = {'form': form, 'success': success} + return render_to_response('registered/discord.html', context, context_instance=RequestContext(request)) diff --git a/stock/templates/registered/discord.html b/stock/templates/registered/discord.html new file mode 100644 index 00000000..4204d5fe --- /dev/null +++ b/stock/templates/registered/discord.html @@ -0,0 +1,33 @@ +{% extends "public/base.html" %} +{% load bootstrap %} +{% load staticfiles %} + +{% block title %}Alliance Auth{% endblock %} + +{% block page_title %}Jabber Broadcast{% endblock page_title %} +{% block extra_css %}{% endblock extra_css %} + +{% block content %} +
+

Discord Connection

+ +
+
+
+ {% if success %} + + {% endif %} +

Enter your discord account credentials below. These are not stored: they are needed to determine your user ID and make you join the server.

+ +
+
+
+
+ +{% endblock content %} diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 0f65ed09..9a40e658 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -117,11 +117,11 @@ {% if ENABLE_BLUE_DISCORD %} Discord - {{ authinfo.discord_username }} - {{ authinfo.discord_password }} + {{ authinfo.discord_uid }} +
https://discordapp.com - {% ifequal authinfo.discord_username "" %} + {% ifequal authinfo.discord_uid "" %} @@ -288,11 +288,11 @@ {% if ENABLE_AUTH_DISCORD %} Discord - {{ authinfo.discord_username }} - {{ authinfo.discord_password }} + {{ authinfo.discord_uid }} + https://discordapp.com - {% ifequal authinfo.discord_username "" %} + {% ifequal authinfo.discord_uid "" %} diff --git a/util/common_task.py b/util/common_task.py index eb61672e..fe312f95 100755 --- a/util/common_task.py +++ b/util/common_task.py @@ -42,9 +42,9 @@ def deactivate_services(user): if authinfo.teamspeak3_uid and authinfo.teamspeak3_uid != "": Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) AuthServicesInfoManager.update_user_teamspeak3_info("", "", user) - if authinfo.discord_username and authinfo.discord_username != "": - DiscordManager.lock_user(authinfo.discord_username) - AuthServicesInfoManager.update_user_discord_info("", "", user) + if authinfo.discord_uid and authinfo.discord_uid != "": + DiscordManager.delete_user(authinfo.discord_uid) + AuthServicesInfoManager.update_user_discord_info("", user) def generate_corp_group_name(corpname): From ae38f8f01f3988a6ab416e592a2670932509a491 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 01:08:15 +0000 Subject: [PATCH 24/30] Corrected parameter checked for Discord account activation. --- celerytask/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/celerytask/tasks.py b/celerytask/tasks.py index af5b322c..d8b71aa9 100755 --- a/celerytask/tasks.py +++ b/celerytask/tasks.py @@ -163,7 +163,7 @@ def add_to_databases(user, groups, syncgroups): if syncgroups.filter(groupname=group.name).filter(servicename="ipboard").exists() is not True: create_syncgroup_for_user(user, group.name, "ipboard") update_ipboard_groups(user) - if authserviceinfo.discord_username and authserviceinfo.discord_username != "": + if authserviceinfo.discord_uid and authserviceinfo.discord_uid != "": if syncgroups.filter(groupname=group.name).filter(servicename="discord").exists() is not True: create_syncgroup_for_user(user, group.name, "discord") update_discord_groups(user) From a388e2595ee58c591269babf8ce7fbfd53570b1a Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 01:18:59 +0000 Subject: [PATCH 25/30] Cleaned up redundant functions. --- services/managers/discord_manager.py | 33 ---------------------------- services/views.py | 15 +------------ 2 files changed, 1 insertion(+), 47 deletions(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 3613833a..80c90609 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -280,31 +280,6 @@ class DiscordManager: def __generate_random_pass(): return os.urandom(8).encode('hex') - @staticmethod - def old_add_user(username, email): - try: - username_clean = DiscordManager.__sanatize_username(username) - invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] - password = DiscordManager.__generate_random_pass() - DiscordAPIManager.register_user(server_id=settings.DISCORD_SERVER_ID, username=username_clean, invite_code=invite_code, password=password, email=email) - user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username_clean) - DiscordAPIManager.delete_invite(invite_code) - return username_clean, password - except: - return "", "" - - @staticmethod - def old_delete_user(username, email, password): - try: - user_id = DiscordAPIManager.get_user_id(settings.DISCORD_SERVER_ID, username) - DiscordAPIManager.kick_user(settings.DISCORD_SERVER_ID, user_id) - DiscordAPIManager.destroy_user(email, password) - return True - except: - #something went wrong - return False - return False - @staticmethod def update_groups(user_id, groups): group_ids = [] @@ -348,14 +323,6 @@ class DiscordManager: except: return current_password - @staticmethod - def get_user_id(email, password): - try: - profile = DiscordAPIManager.get_user_profile(email, password) - return profile['user']['id'] - except: - return "" - @staticmethod def add_user(email, password): try: diff --git a/services/views.py b/services/views.py index 232c7a4b..eb856665 100755 --- a/services/views.py +++ b/services/views.py @@ -321,19 +321,6 @@ def fleet_fits(request): return render_to_response('registered/fleetfits.html', context, context_instance=RequestContext(request)) -@login_required -@user_passes_test(service_blue_alliance_test) -def old_activate_discord(request): - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - character = EveManager.get_character_by_id(authinfo.main_char_id) - info = DiscordManager.add_user(character.character_name, request.user.email) - # If our username is blank means we already had a user - if info[0] is not "": - AuthServicesInfoManager.update_user_discord_info(info[0], info[1], request.user) - update_discord_groups(request.user) - return HttpResponseRedirect("/services/") - return HttpResponseRedirect("/dashboard") - @login_required @user_passes_test(service_blue_alliance_test) def deactivate_discord(request): @@ -341,7 +328,7 @@ def deactivate_discord(request): result = DiscordManager.delete_user(authinfo.discord_uid) remove_all_syncgroups_for_service(request.user, "discord") if result: - AuthServicesInfoManager.update_user_discord_info("",request.user) + AuthServicesInfoManager.update_user_discord_info("", request.user) return HttpResponseRedirect("/services/") return HttpResponseRedirect("/dashboard") From 563967bf0d7e9ad2a86889d798909fcf2a12fee0 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 01:39:06 +0000 Subject: [PATCH 26/30] Updated form to a password input for security. DiscordManager now strips groups before kicking. This prevents server owners from keeping groups if they connect account with auth. --- services/forms.py | 2 +- services/managers/discord_manager.py | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/services/forms.py b/services/forms.py index f96c404b..0696c939 100644 --- a/services/forms.py +++ b/services/forms.py @@ -27,4 +27,4 @@ class FleetFormatterForm(forms.Form): class DiscordForm(forms.Form): email = forms.CharField(label="Email Address", required=True) - password = forms.CharField(label="Password", required=True) + password = forms.CharField(label="Password", required=True, widget=forms.PasswordInput) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 80c90609..b226eedc 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -283,13 +283,16 @@ class DiscordManager: @staticmethod def update_groups(user_id, groups): group_ids = [] - for g in groups: - try: - group_id = DiscordAPIManager.get_group_id(settings.DISCORD_SERVER_ID, g) - group_ids.append(group_id) - except: - # need to create role on server for group - group_ids.append(DiscordManager.create_group(g)) + if len(groups) == 0: + group_ids = [] + else: + for g in groups: + try: + group_id = DiscordAPIManager.get_group_id(settings.DISCORD_SERVER_ID, g) + group_ids.append(group_id) + except: + # need to create role on server for group + group_ids.append(DiscordManager.create_group(g)) DiscordAPIManager.set_roles(settings.DISCORD_SERVER_ID, user_id, group_ids) @staticmethod @@ -340,6 +343,7 @@ class DiscordManager: @staticmethod def delete_user(user_id): try: + DiscordManager.update_groups(user_id, []) DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) return True except: From b9db6fc38cfa442f95ec57dc073bd337ad55285c Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 03:22:18 +0000 Subject: [PATCH 27/30] Reduced number of api calls to improve response time. --- services/managers/discord_manager.py | 176 ++++++++++++++------------- 1 file changed, 91 insertions(+), 85 deletions(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index b226eedc..f6fbe94b 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -8,8 +8,28 @@ DISCORD_URL = "https://discordapp.com/api" class DiscordAPIManager: - def __init__(self): - pass + def __init__(self, server_id, email, 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)) + r.raise_for_status() + self.token = r.json()['token'] + self.email = email + self.password = password + self.server_id = server_id + + def __del__(self): + if hasattr(self, 'token'): + if self.token and self.token != "": + data = {'token': self.token} + path = DISCORD_URL + "/auth/logout" + custom_headers = {'content-type':'application/json'} + r = requests.post(path, headers=custom_headers, data=json.dumps(data)) + r.raise_for_status() @staticmethod def get_auth_token(): @@ -23,88 +43,77 @@ class DiscordAPIManager: r.raise_for_status() return r.json()['token'] - @staticmethod - def add_server(name): + def add_server(self, name): data = {"name": name} - custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + 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() - @staticmethod - def rename_server(server_id, name): + def rename_server(self, name): data = {"name": name} - custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + 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() - @staticmethod - def delete_server(server_id): - custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + 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() - @staticmethod - def get_members(server_id): - custom_headers = {'accept':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/members" + 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() - @staticmethod - def get_bans(server_id): - custom_headers = {'accept':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans" + 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() - @staticmethod - def ban_user(server_id, user_id, delete_message_age=0): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) + "?delete-message-days=" + str(delete_message_age) + 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) r.raise_for_status() - @staticmethod - def unban_user(server_id, user_id): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/bans/" + str(user_id) + 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) r.raise_for_status() - @staticmethod - def generate_role(server_id): - custom_headers = {'accept':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles" + 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) r.raise_for_status() return r.json() - @staticmethod - def edit_role(server_id, role_id, name, color=0, hoist=True, permissions=36785152): - custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_auth_token()} + 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(server_id) + "/roles/" + str(role_id) + path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/roles/" + str(role_id) r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) r.raise_for_status() return r.json() - - @staticmethod - def delete_role(server_id, role_id): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles/" + str(role_id) + 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() @@ -124,10 +133,9 @@ class DiscordAPIManager: r.raise_for_status() return r.json() - @staticmethod - def create_invite(server_id, max_age=600, max_uses=1, temporary=True, xkcdpass=False): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/channels/" + str(server_id) + "/invites" + 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, @@ -138,17 +146,15 @@ class DiscordAPIManager: r.raise_for_status() return r.json() - @staticmethod - def delete_invite(invite_id): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} + 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() - @staticmethod - def set_roles(server_id, user_id, role_ids): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token(), 'content-type':'application/json'} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/members/" + str(user_id) + 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)) r.raise_for_status() @@ -167,40 +173,35 @@ class DiscordAPIManager: r = requests.post(path, headers=custom_headers, data=json.dumps(data)) r.raise_for_status() - @staticmethod - def kick_user(server_id, user_id): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token()} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/members/" + str(user_id) + 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() - @staticmethod - def get_members(server_id): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token(), 'accept':'application/json'} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/members" + 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() - @staticmethod - def get_user_id(server_id, username): - all_members = DiscordAPIManager.get_members(server_id) + 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) - @staticmethod - def get_roles(server_id): - custom_headers = {'authorization': DiscordAPIManager.get_auth_token(), 'accept':'application/json'} - path = DISCORD_URL + "/guilds/" + str(server_id) + "/roles" + 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) r.raise_for_status() return r.json() - @staticmethod - def get_group_id(server_id, group_name): - all_roles = DiscordAPIManager.get_roles(server_id) + def get_group_id(self, group_name): + all_roles = self.get_roles() for role in all_roles: if role['name'] == group_name: return role['id'] @@ -259,9 +260,8 @@ class DiscordAPIManager: r.raise_for_status return r.json() - @staticmethod - def check_if_user_banned(server_id, user_id): - bans = DiscordAPIManager.get_bans(server_id) + 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 @@ -283,28 +283,31 @@ class DiscordManager: @staticmethod def update_groups(user_id, groups): group_ids = [] + api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) if len(groups) == 0: group_ids = [] else: for g in groups: try: - group_id = DiscordAPIManager.get_group_id(settings.DISCORD_SERVER_ID, g) + group_id = api.get_group_id(g) group_ids.append(group_id) except: # need to create role on server for group - group_ids.append(DiscordManager.create_group(g)) - DiscordAPIManager.set_roles(settings.DISCORD_SERVER_ID, user_id, group_ids) + group_ids.append(api.create_group(g)) + api.set_roles(user_id, group_ids) @staticmethod def create_group(groupname): - new_group = DiscordAPIManager.generate_role(settings.DISCORD_SERVER_ID) - named_group = DiscordAPIManager.edit_role(settings.DISCORD_SERVER_ID, new_group['id'], groupname) + api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) + new_group = api.generate_role() + named_group = api.edit_role(new_group['id'], groupname) return named_group['id'] @staticmethod def lock_user(user_id): try: - DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) + api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) + api.ban_user(user_id) return True except: return False @@ -312,7 +315,8 @@ class DiscordManager: @staticmethod def unlock_user(user_id): try: - DiscordAPIManager.unban_user(settings.DISCORD_SERVER_ID, user_id) + api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) + api.unban_user(user_id) return True except: return False @@ -329,11 +333,12 @@ class DiscordManager: @staticmethod def add_user(email, password): try: + api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) profile = DiscordAPIManager.get_user_profile(email, password) user_id = profile['id'] - if DiscordAPIManager.check_if_user_banned(settings.DISCORD_SERVER_ID, user_id): - DiscordAPIManager.unban_user(settings.DISCORD_SERVER_ID, user_id) - invite_code = DiscordAPIManager.create_invite(settings.DISCORD_SERVER_ID)['code'] + if api.check_if_user_banned(user_id): + api.unban_user(user_id) + invite_code = api.create_invite()['code'] token = DiscordAPIManager.get_token_by_user(email, password) DiscordAPIManager.accept_invite(invite_code, token) return user_id @@ -343,8 +348,9 @@ class DiscordManager: @staticmethod def delete_user(user_id): try: + api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) DiscordManager.update_groups(user_id, []) - DiscordAPIManager.ban_user(settings.DISCORD_SERVER_ID, user_id) + api.ban_user(user_id) return True except: return False From 7e371e34f8891e3c85fa198c5a9c8045521418da Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 03:31:12 +0000 Subject: [PATCH 28/30] Hid Discord user ID as it adds nothing and can confuse members. --- stock/templates/registered/services.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/templates/registered/services.html b/stock/templates/registered/services.html index 9a40e658..9a9f7541 100755 --- a/stock/templates/registered/services.html +++ b/stock/templates/registered/services.html @@ -117,7 +117,7 @@ {% if ENABLE_BLUE_DISCORD %} Discord - {{ authinfo.discord_uid }} + https://discordapp.com @@ -288,7 +288,7 @@ {% if ENABLE_AUTH_DISCORD %} Discord - {{ authinfo.discord_uid }} + https://discordapp.com From 286910059bec262bc51cabd1cdc28617b913ff1d Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 03:57:54 +0000 Subject: [PATCH 29/30] Moved syncgroup deletion into block ensuring user was deleted. --- services/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/views.py b/services/views.py index eb856665..a3730b76 100755 --- a/services/views.py +++ b/services/views.py @@ -326,8 +326,8 @@ context_instance=RequestContext(request)) def deactivate_discord(request): authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) result = DiscordManager.delete_user(authinfo.discord_uid) - remove_all_syncgroups_for_service(request.user, "discord") if result: + remove_all_syncgroups_for_service(request.user, "discord") AuthServicesInfoManager.update_user_discord_info("", request.user) return HttpResponseRedirect("/services/") return HttpResponseRedirect("/dashboard") From f342569f16a7db6d6ebc757a208d462a12a28549 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Wed, 2 Dec 2015 04:22:48 +0000 Subject: [PATCH 30/30] Corrected reference to wrong manager in group creation. --- services/managers/discord_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index f6fbe94b..b9ed5398 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -293,7 +293,7 @@ class DiscordManager: group_ids.append(group_id) except: # need to create role on server for group - group_ids.append(api.create_group(g)) + group_ids.append(DiscordManager.create_group(g)) api.set_roles(user_id, group_ids) @staticmethod