""" The user controller to manage all of the user related endpoints in the web app """ from flask import Blueprint from flask import render_template, redirect, request, session, flash, url_for from controllers.database.user import UserController from models.users.customer import Customer from models.users.seller import Seller from models.users.user import User from utils.user_utils import is_role from hashlib import sha512 # Blueprint to append user endpoints to blueprint = Blueprint("users", __name__, url_prefix="/users") ROLES = [ "Customer", "Seller", "Admin" ] @blueprint.context_processor def roles_list(): """ Places a list of all the available roles in the users context """ return dict(roles=ROLES) # LOGIN FUNCTIONALITY @blueprint.route('/login') def display_login(): """ Function responsible for delivering the Login page for the site """ return render_template('index.html', content="login.html") @blueprint.post('/login') def login(): """ Function to handle the backend processing of a login request """ database = UserController() user = database.read(request.form['username']) error = None # No user found if user is None: error = "No user found with the username " + request.form['username'] flash(error, 'warning') return redirect(url_for('main.users.login')) # Incorrect Password if sha512(request.form['password'].encode()).hexdigest() != user.password: error = "Incorrect Password" flash(error, 'warning') return redirect(url_for('main.users.login')) session['user_id'] = user.id return redirect(url_for('main.index')) # SIGNUP FUNCTIONALITY @blueprint.route('/update/') def display_update(id: int): """ Function responsible for delivering the Update User page for the site """ db = UserController() user = db.read_id(id) return render_template( 'index.html', content="user.html", updating_user=user ) @blueprint.post('/update/') def update(id: int): """ Function to handle the backend processing of a signup request """ if not is_role("Admin"): flash("You must be logged in an admin to update users!", "error") return redirect(url_for('main.index')) user = User( request.form['username'], "", # Password request.form['firstname'], request.form['lastname'], request.form['email'], request.form['phone'], request.form['role'], ) user.id = id db = UserController() checking_user = db.read(user.username) # User with this new username is already taken if checking_user is not None and checking_user.id != user.id: flash( f"User with the username {user.username} already exists!", "warning" ) return redirect(url_for('main.users.display_update', id=id)) # Invalid role submitted if user.role not in ROLES: flash( f"Selected role, {user.role}, is not valid!", "warning" ) return redirect(url_for('main.users.display_update', id=id)) db.update(user) return redirect(url_for('main.admin.users')) # SIGN OUT FUNCTIONALITY @blueprint.route('/logout') def logout(): """ Function responsible for handling logouts from the site """ # Clear the current user from the session if they are logged in session.pop('user_id', None) return redirect(url_for('main.index')) # SIGNUP FUNCTIONALITY @blueprint.route('/signup') def display_signup(): """ Function responsible for delivering the Signup page for the site """ return render_template('index.html', content="signup.html") @blueprint.post('/signup') def signup(): """ Function to handle the backend processing of a signup request """ database = UserController() # User already exists if database.read(request.form['username']) is not None: error = "User, " + request.form['username'] + " already exists" flash(error, 'warning') return redirect(url_for('main.users.signup')) # Signup as Seller or Customer if request.form.get('seller'): user = Seller( request.form['username'], # Hashed as soon as it is recieved on the backend sha512(request.form['password'].encode()).hexdigest(), request.form['firstname'], request.form['lastname'], request.form['email'], "123" ) else: user = Customer( request.form['username'], # Hashed as soon as it is recieved on the backend sha512(request.form['password'].encode()).hexdigest(), request.form['firstname'], request.form['lastname'], request.form['email'], "123" ) database.create(user) # Code 307 Preserves the original request (POST) return redirect(url_for('main.users.login'), code=307) # DELETE USER FUNCTIONALITY @blueprint.post('/delete/') def delete(id: int): """ Function responsible for deleting users from the site """ if not is_role("Admin"): flash("You must be logged in an admin to remove users!", "error") return redirect(url_for('main.index')) db = UserController() db.delete(id) return redirect(url_for('main.admin.users'))