aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2022-09-20 17:58:27 -0400
committerCara Salter <cara@devcara.com>2022-09-20 17:58:27 -0400
commitb1ffd5220866dc9479fa284dfb2f0a0e111a6031 (patch)
treec63661f965a4a4e99888f23f28619d5a61e7244a
parente549bc0a5c39e85fb94cb289497f1b245b564947 (diff)
downloadnccd-b1ffd5220866dc9479fa284dfb2f0a0e111a6031.tar.gz
nccd-b1ffd5220866dc9479fa284dfb2f0a0e111a6031.zip
auth
-rw-r--r--README.md2
-rw-r--r--app/__init__.py16
-rw-r--r--app/auth/__init__.py75
-rw-r--r--app/auth/forms.py15
-rw-r--r--app/config.py3
-rw-r--r--app/database.py21
-rw-r--r--app/meta/__init__.py10
-rw-r--r--app/static/gen/style.css35
-rw-r--r--app/static/scss/style.scss48
-rw-r--r--app/templates/base.html36
-rw-r--r--app/templates/index.html5
-rw-r--r--app/templates/login.html14
-rw-r--r--app/templates/register.html5
13 files changed, 258 insertions, 27 deletions
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 @@
+<!DOCTYPE html>
+
+<html>
+ <head>
+ <title>nccd</title>
+ {% assets "scss" %}
+ <link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}">
+ {% endassets %}
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ </head>
+
+ <body>
+ <div class="container">
+ <div class="navbar">
+ <ul>
+ <li class="navbar-item"><a href="/">Home</a></li>
+ </ul>
+ </div>
+ {% with messages = get_flashed_messages() %}
+ {% if messages %}
+ <ul class="flashes">
+ {% for m in messages %}
+ <li class="message">{{m}}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% endwith %}
+
+ {% block content %}
+
+ Whoops! This page is still being worked on.
+
+ {% endblock %}
+ </div>
+ </body>
+</html>
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 method="POST">
+ {{ form.csrf_token }}
+ <div>
+ {{form.username.label }}{{form.username}}
+ </div>
+ <div>
+ {{form.password.label}}{{form.password}}
+ </div>
+ {{form.submit}}
+</form>
+{% 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 %}