diff options
Diffstat (limited to 'app/modules')
| -rw-r--r-- | app/modules/__init__.py | 4 | ||||
| -rw-r--r-- | app/modules/auth/forms.py | 34 | ||||
| -rw-r--r-- | app/modules/auth/routes.py | 73 | ||||
| -rw-r--r-- | app/modules/common.py | 75 | 
4 files changed, 186 insertions, 0 deletions
diff --git a/app/modules/__init__.py b/app/modules/__init__.py new file mode 100644 index 0000000..fcd1d43 --- /dev/null +++ b/app/modules/__init__.py @@ -0,0 +1,4 @@ +# -*- mode: python; -*- + +from .common import common +from .auth.routes import auth diff --git a/app/modules/auth/forms.py b/app/modules/auth/forms.py new file mode 100644 index 0000000..a4b4555 --- /dev/null +++ b/app/modules/auth/forms.py @@ -0,0 +1,34 @@ +# -*- mode: python; -*- + + +from flask_wtf import FlaskForm +from wtforms import ( +    SubmitField, +    HiddenField, +    StringField, +    PasswordField, +    BooleanField, +) +from wtforms.validators import ( +    InputRequired, +    Length, +    ValidationError, +) + + +class LoginForm(FlaskForm): +    username = StringField("Username", validators=[InputRequired()]) +    password = PasswordField("Password", validators=[InputRequired()]) +    remember = BooleanField("Remember") +    submit = SubmitField("Login") + + +class RegisterForm(LoginForm): +    def validate_invite_code(self, field): +        if field.data != "mdltesters2022": +            raise ValidationError("Invitation code does not match") + +    invitation_code = StringField("Invitation code", validators=[InputRequired()]) +    name_first = StringField("First name", validators=[InputRequired()]) +    name_last = StringField("Last name", validators=[InputRequired()]) +    submit = SubmitField("Register") diff --git a/app/modules/auth/routes.py b/app/modules/auth/routes.py new file mode 100644 index 0000000..db59bf1 --- /dev/null +++ b/app/modules/auth/routes.py @@ -0,0 +1,73 @@ +# -*- mode: python; -*- + +from flask import Blueprint, render_template, redirect, url_for, request, flash +from flask_login import login_user, login_required, logout_user +from werkzeug.security import generate_password_hash, check_password_hash + +from ... import db +from ...models import User +from .forms import LoginForm, RegisterForm + + +auth = Blueprint("auth", __name__) + + +@auth.route("/login", methods=["GET", "POST"]) +def login(): +    form = LoginForm() +    if form.validate_on_submit(): +        req = request.form +        # print(req["remember"]) +        remember = True if req.get("remember") else False +        user = User.query.filter_by(username=req["username"]).first() +        if user is None: +            flash("User not registered.", "error") +            return redirect(url_for("auth.register")) +        if check_password_hash(user.hashed_password, req["password"]) is False: +            flash("Wrong password.", "error") +            return redirect(url_for("auth.login")) +        login_user(user, remember=remember) +        flash( +            f"Logged in as user {user.username} successfully. " +            + f"You will{' not ' if remember is False else ' '}be remembered next time!" +        ) +        return redirect(url_for("main.home")) +    return render_template("modules/login.html", form=form) + + +@auth.route("/register", methods=["GET", "POST"]) +def register(): +    form = RegisterForm() +    if form.validate_on_submit(): +        req = request.form +        user_already_exists = User.query.filter_by( +            name_first=req["name_first"], +            name_last=req["name_last"], +        ).first() +        if user_already_exists: +            flash( +                f"User {req['name_first']} {req['name_last']} already exists.", "error" +            ) +            return redirect(url_for("auth.login")) +        if req["invitation_code"] != "mdltesters2022": +            flash("Wrong invitation code.", "error") +            return redirect(url_for("auth.register")) +        new_user = User( +            username=req["username"], +            hashed_password=generate_password_hash(req["password"], method="sha256"), +            name_first=req["name_first"], +            name_last=req["name_last"], +        ) +        db.session.add(new_user) +        db.session.commit() +        flash(f"Created user {req['name_first']} {req['name_last']} successfully.") +        return redirect(url_for("main.home")) +    return render_template("modules/register.html", form=form) + + +@auth.route("/logout") +@login_required +def logout(): +    logout_user() +    flash(f"Logged out successfully.") +    return redirect(url_for("main.home")) diff --git a/app/modules/common.py b/app/modules/common.py new file mode 100644 index 0000000..1250878 --- /dev/null +++ b/app/modules/common.py @@ -0,0 +1,75 @@ +# -*- mode: python; -*- + +import inspect +from flask import Blueprint, request, render_template, redirect, flash, jsonify +from flask_login import login_required, current_user + +from .. import db +from .. import models +# from . import forms + +from wtforms import SelectField + + +common = Blueprint("common", __name__) + + +@common.route("/modules/<module>/add/<table>", methods=["GET", "POST"]) +@login_required +def add_item(module, table): +    """Add new item to table accessible via module.""" +    # print("db table keys are", db.metadata.tables.keys()) +    if table not in db.metadata.tables.keys(): +        return render_template("errors/item-not-found.html", table=table) +    form = getattr(forms, f"Add{table}")() +    if form.validate_on_submit(): +        model = getattr(models, table) +        table_fields = inspect.signature(model).parameters +        form_values = {key: request.form.get(key) for key in table_fields} +        print(f"Ready to insert in {table} from {module} {form_values}") +        record = model(**form_values) +        db.session.add(record) +        db.session.commit() +        item_pk = model.query.order_by(model.primary_key.desc()).first().primary_key +        flash(f"Successfully added item #{item_pk} to {table} table.", "info") +        return redirect(f"/modules/{module}") +    return render_template("modules/add-item.html", table=table, form=form) + + +@common.route("/modules/<module>/edit/<table>/<int:pk>", methods=["GET", "POST"]) +@login_required +def edit_item(module, table, pk): +    """Edit existing item in table accessible via module.""" +    if table not in db.metadata.tables.keys(): +        return render_template("errors/item-not-found.html", table=table) +    model = getattr(models, table) +    item = model.query.filter_by(primary_key=pk).first() +    # Instantiate form with selected item's field values. +    form = getattr(forms, f"Add{table}")(**item.__dict__) +    if form.validate_on_submit(): +        table_fields = inspect.signature(model).parameters +        form_values = {key: request.form.get(key) for key in table_fields} +        print(f"Ready to update {form_values}") +        model.query.filter_by(primary_key=pk).update(form_values) +        db.session.commit() +        flash(f"Successfully edited item #{pk} in {table} table.", "info") +        return redirect(f"/modules/{module}") +    return render_template("modules/edit-item.html", table=table, pk=pk, form=form) + + +@common.route("/modules/<module>/delete/<table>/<int:pk>", methods=["POST"]) +@login_required +def delete_item(module, table, pk): +    """Delete item with Primary Key = pk from table in module.""" +    model = getattr(models, table) +    record = model.query.filter_by(primary_key=pk).first() +    db.session.delete(record) +    db.session.commit() +    flash(f"Successfully removed item #{pk} from {table} table.", "info") +    return redirect(f"/modules/{module}") + + +@common.route("/modules/settings") +@login_required +def settings(): +    return render_template("modules/settings.html", user=current_user)  |