-
-
Save xapple/bb8fe6a2adca9cbf86675cb48b59f0be to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This submodule is inspired from the dash-flask-login library at: | |
https://github.com/gaw89/dash-flask-login | |
It is unlicensed. | |
To implement this in your dash app, add this file auth.py to your superproject | |
and do something like this in your server script: | |
from superproject.auth import FlaskLoginAuth | |
server = Flask("superproject") | |
app = Dash(name='superproject', server=server, url_base_pathname='/') | |
users = [('steven', 'vc98zq23jkhjyxcvoi')] | |
auth = FlaskLoginAuth(app, users=users) | |
Be sure to create /assets/login.html with a log-in form for it to work. | |
""" | |
# Modules # | |
import os, hashlib, flask | |
# Flask # | |
from flask import request, redirect, url_for | |
from flask_login import login_required, LoginManager, UserMixin, login_user | |
############################################################################### | |
class DefaultUser(UserMixin): | |
def __init__(self, name, password, hash_function): | |
self.id = name.lower() | |
self.username = name.lower() | |
self.password = hash_function(password) | |
def __eq__(self, other): | |
return self.id == other.id | |
############################################################################### | |
class UserMap(object): | |
def __init__(self, users): | |
"""*users* is a list of DefaultUser objects""" | |
self.users = users | |
self.user_map = {} | |
for u in self.users: self.user_map.update({u.id: u}) | |
def get_user(self, id): | |
try: return self.user_map[id] | |
except: return None | |
############################################################################### | |
class FlaskLoginAuth(): | |
def __init__(self, app, users): | |
""" | |
app: A Dash object to be login-protected | |
users: Should be a list of tuples of the format (<USERNAME>, <PASSWORD>) | |
where each element is a unicode string. | |
This will be used to create a list of DefaultUser objects. | |
""" | |
# Basic attributes # | |
self.server = app.server | |
# Users # | |
self.users = UserMap([DefaultUser(u[0], u[1], self.hash_function) for u in users]) | |
# Alter the view functions of the server to require login # | |
self.server.view_functions['/view'] = login_required(self.server.view_functions['/view']) | |
# Setup the LoginManager for the server # | |
self.login_manager = LoginManager() | |
self.login_manager.init_app(self.server) | |
self.login_manager.login_view = "/login" | |
# Secret Key # | |
self.server.config.update(SECRET_KEY = os.urandom(12)) | |
# Callback to reload the user object # | |
@self.login_manager.user_loader | |
def load_user(userid): | |
return self.users.get_user(userid) | |
# The default templates # | |
current_directory = os.path.dirname(os.path.abspath(__file__)) | |
self.login_html = current_directory + '/assets/login.html' | |
# Rule # | |
self.server.add_url_rule( | |
'/login', | |
view_func = self.default_login_view, | |
methods = ['GET', 'POST'] | |
) | |
# Base route goes to login # | |
@self.server.route('/', methods=['GET']) | |
def save(): | |
return redirect(url_for('default_login_view')) | |
def hash_function(self, string): | |
return hashlib.md5().update(string.encode('utf-8')).hexdigest() | |
def default_login_view(self): | |
if request.method == 'POST': | |
username = request.form['username'].lower() | |
password = request.form['password'] | |
password = self.hash_function(password) | |
user = self.users.get_user(username) | |
if user: | |
if password == user.password: | |
login_user(user) | |
return redirect(flask.url_for('/view')) | |
return flask.send_file(self.login_html) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment