From 1889f3248ae83cc773a5443c6ba0f62834d73b7b Mon Sep 17 00:00:00 2001 From: Nate the great Date: Thu, 29 Mar 2018 04:52:29 -0400 Subject: Oauth (#45) * Creating a OAUTH login for the site. We still need to have a way to fill in credentials however. Signed-off-by: Zwork101 * How ya like me now Travis? Signed-off-by: Zwork101 * Fix slight error in database insertion * Revert "Fix slight error in database insertion" (wrong branch) This reverts commit 9ac6cbb * Don't have snekchek working, but I'll try again. Signed-off-by: Zwork101 * Please enter the commit message for your changes. Lines starting * Adding Oauth2 login to site. * Add prefix * Add prefix * This never happened * Flipping Travis I still can't get snekchek to work locally. * Added a whole bunch of stuff, ready to be used. Signed-off-by: Zwork101 * Making sessions more secure, and future safe. Signed-off-by: Zwork101 * Adding some quick stuff Signed-off-by: Zwork101 * Appease the flake8 gods Signed-off-by: Zwork101 * Appease the flake8 gods Signed-off-by: Zwork101 * Whoops Signed-off-by: Zwork101 * Add comments, fix user_data function. Signed-off-by: Zwork101 * Whooops, forgot to flake :/ Signed-off-by: Zwork101 * Make it look nicer, thanks Aperture. Signed-off-by: Zwork101 * Fixing login issues and added button * Add a OauthMixin to allow for easy data access. Clean stuff up. Signed-off-by: Zwork101 * Fix a test, and use self.assertEqual rather then self.assertEquals! Signed-off-by: Zwork101 * Please don't ask how that happened. Signed-off-by: Zwork101 * Added some tests, moved a bunch of stuff around. Mainly cleaned stuff up. Signed-off-by: Zwork101 * Add a ton of tests, try to please the coverall gods :D, moved some code into a function for testing. Signed-off-by: Zwork101 * Just some stupid stuff I missed. Signed-off-by: Zwork101 * Fix an issue with the test, and add docs Signed-off-by: Zwork101 * Remove pointless function. (join_user) Signed-off-by: Zwork101 * Fix test consistency --- pysite/oauth.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 pysite/oauth.py (limited to 'pysite/oauth.py') diff --git a/pysite/oauth.py b/pysite/oauth.py new file mode 100644 index 00000000..8370b713 --- /dev/null +++ b/pysite/oauth.py @@ -0,0 +1,77 @@ +import logging +from uuid import uuid4, uuid5 + +from flask import session +from flask_dance.consumer.backend import BaseBackend +from flask_dance.contrib.discord import discord + + +from pysite.constants import DISCORD_API_ENDPOINT, OAUTH_DATABASE + + +class OauthBackend(BaseBackend): + """ + This is the backend for the oauth + + This is used to manage users that have completed + an oauth dance. It contains 3 functions, get, set, + and delete, however we only use set. + + Inherits: + flake_dance.consumer.backend.BaseBackend + pysite.mixins.DBmixin + + Properties: + key: The app's secret, we use it too make session IDs + """ + + def __init__(self, manager): + super().__init__() + self.db = manager.db + self.key = manager.app.secret_key + self.db.create_table(OAUTH_DATABASE, primary_key="id") + + def get(self, *args, **kwargs): # Not used + pass + + def set(self, blueprint, token): + + user = self.get_user() + self.join_discord(token["access_token"], user["id"]) + sess_id = str(uuid5(uuid4(), self.key)) + self.add_user(token, user, sess_id) + + def delete(self, blueprint): # Not used + pass + + def add_user(self, token_data: dict, user_data: dict, session_id: str): + session["session_id"] = session_id + + self.db.insert(OAUTH_DATABASE, {"id": session_id, + "access_token": token_data["access_token"], + "refresh_token": token_data["refresh_token"], + "expires_at": token_data["expires_at"], + "snowflake": user_data["id"]}) + + self.db.insert("users", {"user_id": user_data["id"], + "username": user_data["username"], + "discriminator": user_data["discriminator"], + "email": user_data["email"]}) + + def get_user(self) -> dict: + resp = discord.get(DISCORD_API_ENDPOINT + "/users/@me") # 'discord' is a request.Session with oauth information + if resp.status_code != 200: + logging.warning("Unable to get user information: " + str(resp.json())) + return resp.json() + + def user_data(self): + user_id = session.get("session_id") + if user_id: # If the user is logged in, get user info. + creds = self.db.get(OAUTH_DATABASE, user_id) + if creds: + return self.db.get("users", creds["snowflake"]) + + def logout(self): + sess_id = session.get("session_id") + if sess_id and self.db.get(OAUTH_DATABASE, sess_id): # If user exists in db, + self.db.delete(OAUTH_DATABASE, sess_id) # remove them (at least, their session) -- cgit v1.2.3