From b1ffd5220866dc9479fa284dfb2f0a0e111a6031 Mon Sep 17 00:00:00 2001 From: Cara Salter Date: Tue, 20 Sep 2022 17:58:27 -0400 Subject: auth --- README.md | 2 ++ app/__init__.py | 16 +++++----- app/auth/__init__.py | 75 ++++++++++++++++++++++++++++++++++++++++++++- app/auth/forms.py | 15 ++++++--- app/config.py | 3 -- app/database.py | 21 +++++++++++-- app/meta/__init__.py | 10 ++++++ app/static/gen/style.css | 35 +++++++++++++++++++-- app/static/scss/style.scss | 48 ++++++++++++++++++++++++----- app/templates/base.html | 36 ++++++++++++++++++++++ app/templates/index.html | 5 +++ app/templates/login.html | 14 +++++++++ app/templates/register.html | 5 +++ 13 files changed, 258 insertions(+), 27 deletions(-) create mode 100644 app/meta/__init__.py create mode 100644 app/templates/base.html create mode 100644 app/templates/index.html create mode 100644 app/templates/login.html create mode 100644 app/templates/register.html diff --git a/README.md b/README.md index edb02bd..644bc50 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,5 @@ So named because of a bad star trek joke Control server for a wireguard VPN system still in-development. + +requires postgres diff --git a/app/__init__.py b/app/__init__.py index e929535..a2486ed 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,9 +1,8 @@ from flask import Flask -from flask_security.datastore import SQLAlchemyUserDatastore from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate -from flask_security.core import Security +from flask_login import LoginManager from flask_assets import Bundle, Environment @@ -11,8 +10,8 @@ from . import config db = SQLAlchemy() migrate = Migrate() -security = Security() environment = Environment() +login = LoginManager() def create_app(): @@ -23,18 +22,19 @@ def create_app(): db.init_app(app) migrate.init_app(app, db) environment.init_app(app) - + login.init_app(app) # Static file init scss = Bundle('scss/style.scss', filters='scss', output='gen/style.css') environment.register('scss', scss) - from .database import User, Role - from .auth import forms as auth_forms - user_datastore = SQLAlchemyUserDatastore(db, User, Role) - security.init_app(app, user_datastore, register_form=auth_forms.ExtendedRegister) + from .database import User, Role + from . import auth + from . import meta + # Blueprints app.register_blueprint(auth.bp) + app.register_blueprint(meta.bp) print(app.url_map) diff --git a/app/auth/__init__.py b/app/auth/__init__.py index 52f0cd7..b419351 100644 --- a/app/auth/__init__.py +++ b/app/auth/__init__.py @@ -1,3 +1,76 @@ -from flask import Blueprint +from flask import Blueprint, request, redirect, url_for, flash, render_template +from flask_login import current_user, login_user +from werkzeug.security import check_password_hash, generate_password_hash + +from app.auth.forms import LoginForm, RegisterForm +from app.database import User +from app import db + +import ulid bp = Blueprint('auth', __name__, url_prefix='/auth') + +@bp.route("/login", methods=["GET", "POST"]) +def login(): + if current_user.is_authenticated: + flash("You are already logged in") + return redirect(url_for("meta.home")) + + form = LoginForm(request.form) + + if request.method == 'POST' and form.validate(): + email = request.form.get('username') + password = request.form.get('password') + + u = User.query.fetch_one().filter_by(email=email) + + if u is not None: + if check_password_hash(u.password, password): + login_user(u) + + flash("Logged in successfully") + + return redirect(url_for("meta.home")) + + else: + flash("Incorrect password") + else: + flash("Incorrect username") + + return render_template("login.html", form=form) + +@bp.route("/register", methods=["GET", "POST"]) +def register(): + if current_user.is_authenticated: + flash("You are already logged in") + return redirect(url_for("meta.home")) + + form = RegisterForm(request.form) + + if request.method == 'POST' and form.validate(): + email = request.form.get("username") + pref_name = request.form.get("pref_name") + password = request.form.get("password") + pw_confirm = request.form.get("password_confirm") + + if password == pw_confirm: + # Passwords match + + user = User( + id=str(ulid.new()), + email=email, + password=generate_password_hash(password), + pref_name=pref_name, + last_login=datetime.now(), + active=True + ) + + db.session.add(user) + db.session.commit() + flask_login.login_user(user) + + return redirect(url_for('meta.home')) + else: + flash("Passwords do not match") + + return render_template("register.html") diff --git a/app/auth/forms.py b/app/auth/forms.py index 4814f48..778e4fb 100644 --- a/app/auth/forms.py +++ b/app/auth/forms.py @@ -1,7 +1,14 @@ -from flask_security.forms import RegisterForm -from wtforms import StringField +from flask_wtf import FlaskForm +from wtforms.fields.simple import PasswordField, StringField, SubmitField from wtforms.validators import DataRequired -class ExtendedRegister(RegisterForm): - pref_name = StringField('Preferred Name', [DataRequired()]) +class LoginForm(FlaskForm): + username = StringField("Email", validators=[DataRequired()]) + password = PasswordField("Password", validators=[DataRequired()]) + submit = SubmitField("Sign in") +class RegisterForm(FlaskForm): + username = StringField("Email", validators=[DataRequired()]) + password = PasswordField("Password", validators=[DataRequired()]) + password_confirm = PasswordField("Confirm Password", validators=[DataRequired()]) + submit = SubmitField("Register") diff --git a/app/config.py b/app/config.py index 29eb2ef..2a157fa 100644 --- a/app/config.py +++ b/app/config.py @@ -6,9 +6,6 @@ def load_config(path): result = { 'SQLALCHEMY_DATABASE_URI': contents['database']['postgres_url'], 'SECRET_KEY': contents['server']['secret_key'], - 'MAIL_SERVER': contents['email']['smtp_server'], - 'MAIL_PORT': contents['email']['smtp_port'], - 'MAIL_USE_TLS': contents['email']['smtp_tls'], 'SECURITY_REGISTERABLE': True, 'SECURITY_PASSWORD_SALT': contents['server']['secret_key'] } diff --git a/app/database.py b/app/database.py index 24e1930..532f971 100644 --- a/app/database.py +++ b/app/database.py @@ -1,7 +1,9 @@ from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String +from sqlalchemy.dialects.postgresql import CIDR from sqlalchemy.orm import relationship, backref from . import db -from flask_security.core import RoleMixin, UserMixin +from . import login +from flask_login import UserMixin class User(db.Model, UserMixin): id = Column(String, primary_key=True) @@ -13,7 +15,7 @@ class User(db.Model, UserMixin): active = Column(Boolean, nullable=False) roles = relationship('Role', secondary='roles_users',backref=backref('users', lazy='dynamic')) -class Role(db.Model, RoleMixin): +class Role(db.Model): id = Column(String, primary_key=True) name = Column(String, unique=True) description = Column(String) @@ -23,3 +25,18 @@ class RolesUsers(db.Model): id = Column(Integer(), primary_key=True) user_id = Column('user_id', String(), ForeignKey('user.id')) role_id = Column('role_id', String(), ForeignKey('role.id')) + +@login.user_loader +def load_user(user_id): + return User.query.filer_by(id=user_id) + + +class Peer(db.Model): + id = Column(String, primary_key=True) + addr = Column(CIDR, nullable=False) + public_key = Column(String, nullable=False) + +class Network(db.Model): + id = Column(String, primary_key=True) + subnet = Column(CIDR, nullable=False) + description = Column(String, nullable=True) diff --git a/app/meta/__init__.py b/app/meta/__init__.py new file mode 100644 index 0000000..4fbe23c --- /dev/null +++ b/app/meta/__init__.py @@ -0,0 +1,10 @@ +from flask import Blueprint +from flask.helpers import flash +from flask.templating import render_template + +bp = Blueprint("meta", __name__) + +@bp.route("/") +def home(): + flash("Test") + return render_template("index.html") diff --git a/app/static/gen/style.css b/app/static/gen/style.css index 6dd2994..9bca965 100644 --- a/app/static/gen/style.css +++ b/app/static/gen/style.css @@ -13,7 +13,8 @@ a a:active, a:visited { width: 60%; } -button { +button, +input[type=submit] { border-radius: 8px; background-color: #458588; border-color: #458588; @@ -26,18 +27,48 @@ button.accent { border-color: #d79921; } +.navbar { + list-style-type: none; + margin: 0; + padding: 0; + border-bottom: 1px solid; + margin-bottom: 2rem; + padding-bottom: 0.4rem; + text-align: center; +} + +.navbar-item { + display: inline; + margin-right: 1rem; +} + +.flashes { + list-style-type: none; + display: flex; +} + +.message { + width: 30%; + justify-content: center; + border: 1px solid #ebdbb2; + background-color: #d79921; + color: black; +} + form { width: 40%; } label, input { + margin-bottom: 0.5rem; + margin-top: 0.5rem; display: inline-block; } label { width: 40%; - text-align: right; + text-align: left; } label + input { diff --git a/app/static/scss/style.scss b/app/static/scss/style.scss index d7f50f7..cc23959 100644 --- a/app/static/scss/style.scss +++ b/app/static/scss/style.scss @@ -1,6 +1,8 @@ $color-bg: #282828; +$color-shadow: #3c3836; $color-fg: #ebdbb2; -$color-accent: #d79921; +$color-accent-bg: #d79921; +$color-accent: #504945; $color-link: #458588; $color-danger: #cc241d; $font-family: monospace; @@ -20,7 +22,8 @@ a a:active, a:visited { width: 60%; } -button { +button, +input[type=submit]{ border-radius: 8px; background-color: $color-link; border-color: $color-link; @@ -29,8 +32,38 @@ button { } button.accent { - background-color: $color-accent; - border-color: $color-accent; + background-color: $color-accent-bg; + border-color: $color-accent-bg; +} + +// Navbar + +.navbar { + list-style-type: none; + margin: 0; + padding: 0; + border-bottom: 1px solid; + margin-bottom: 2rem; + padding-bottom: 0.4rem; + text-align: center; +} +.navbar-item { + display: inline; + margin-right: 1rem; +} + +// Flashed messages +.flashes { + list-style-type: none; + display: flex; +} + +.message { + width: 30%; + justify-content: center; + border: 1px solid $color-fg; + background-color: $color-accent-bg; + color: black; } // Forms @@ -40,17 +73,18 @@ form { label, input { + margin-bottom: 0.5rem; + margin-top: 0.5rem; display: inline-block; } label { width: 40%; - text-align: right; + text-align: left; } label+input { - width: 40%; - + width: 40%; margin: 0 30% 0 4%; } diff --git a/app/templates/base.html b/app/templates/base.html new file mode 100644 index 0000000..d905156 --- /dev/null +++ b/app/templates/base.html @@ -0,0 +1,36 @@ + + + + + nccd + {% assets "scss" %} + + {% endassets %} + + + + +
+ + {% with messages = get_flashed_messages() %} + {% if messages %} + + {% endif %} + {% endwith %} + + {% block content %} + + Whoops! This page is still being worked on. + + {% endblock %} +
+ + diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..3c69e80 --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} + +{% block content %} + +{% endblock %} diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000..21ce281 --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} + +{% block content %} +
+ {{ form.csrf_token }} +
+ {{form.username.label }}{{form.username}} +
+
+ {{form.password.label}}{{form.password}} +
+ {{form.submit}} +
+{% endblock %} diff --git a/app/templates/register.html b/app/templates/register.html new file mode 100644 index 0000000..56d9855 --- /dev/null +++ b/app/templates/register.html @@ -0,0 +1,5 @@ +{% extends 'base.html' %} + +{% block content %} + +{% endblock %} -- cgit v1.2.3