Thanks for the help @nedned!
Iāve included my code below in case anyone needs to implement a login system for nedās Slapdash framework. This method does not include any information on editing, deleting, or updating users in the database - it simply reflects existing users in the user
table of the DB and checks their passwords (assuming the passwords are hashed using bcrypt).
This method protects all dash views as well so people canāt access the dash pages without logging in. To log out, simply access the logout URL (i.e. localhost/logout).
models.py (defined in the slapdash folder)
from slapdash import db
import bcrypt
from flask_login import UserMixin
from slapdash import login
class User(UserMixin, db.Model):
__table__ = db.Model.metadata.tables['user']
def __repr__(self):
return '<User {}>'.format(self.username)
def check_password(self, password):
return bcrypt.checkpw(password.encode('utf8'), self.password.encode('utf8'))
@login.user_loader
def load_user(id):
return User.query.get(int(id))
init.py
...
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
db = SQLAlchemy()
login = LoginManager()
login.login_view = 'login'
bootstrap = Bootstrap()
def create_flask
....
server.config.from_envvar("SLAPDASH_SETTINGS", silent=True)
with server.app_context():
db.init_app(server)
db.Model.metadata.reflect(db.engine) #This part is where I reflect all the tables from my database
from slapdash import models
login.init_app(server)
bootstrap.init_app(server)
return server
settings.py
ā¦
SQLALCHEMY_DATABASE_URI =
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY =
login.html (in slapdash/templates)
{% import 'bootstrap/wtf.html' as wtf %}
<html>
<body>
<div class="login-page">
<div class = 'row'>
<div class ='col-3 offset-1 login-holder'>
<div class="jumbotron logon container">
{{ wtf.quick_form(form, button_map = {'submit': 'danger btn-lg login'}) }}
</div>
</div>
</div>
</div>
</body>
</html>
app.py
from . import create_flask, create_dash
from .layouts import main_layout_header, main_layout_sidebar
from flask import redirect, render_template, url_for, redirect, request, flash
from flask_login import current_user, login_user, logout_user, login_required
from werkzeug.urls import url_parse
from .auth.form import LoginForm
def protect_views(app):
for view_func in app.server.view_functions:
if view_func.startswith('/'):
app.server.view_functions[view_func] = login_required(app.server.view_functions[view_func])
return app
# The Flask instance
server = create_flask()
# The Dash instance
app = create_dash(server)
app = protect_views(app)
from .models import User
@server.route('/')
@server.route('/login', methods = ['GET','POST'])
def login():
if current_user.is_authenticated:
return redirect('/')
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username = form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
next_page = request.args.get('next')
if not next_page or url_parse(next_page).netloc != '':
next_page = '/'
return redirect(next_page)
return render_template('login.html', title='Sign In', form=form)
@server.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
...
The method could definitely be cleaned up but you guys can probably figure that out on your own.
Please let me know if you have issues!