#10 Added ability to update user details

This commit is contained in:
Luke Else 2024-02-14 21:59:31 +00:00
parent d6f7b3e549
commit 3b8be99e15
10 changed files with 340 additions and 211 deletions

View File

@ -69,8 +69,29 @@ class UserController(DatabaseController):
return self.get_many(query, params) return self.get_many(query, params)
def update(self): def update(self, user: User):
print("Doing work") params = [
user.username,
user.firstName,
user.lastName,
user.email,
user.phone,
user.role,
user.id
]
query = """
UPDATE Users
SET username = ?,
first_name = ?,
last_name = ?,
email = ?,
phone = ?,
role = ?
WHERE id = ?
"""
return self.do(query, params)
def delete(self, id: int): def delete(self, id: int):
params = [ params = [

View File

@ -7,12 +7,27 @@ from flask import render_template, redirect, request, session, flash, url_for
from controllers.database.user import UserController from controllers.database.user import UserController
from models.users.customer import Customer from models.users.customer import Customer
from models.users.seller import Seller from models.users.seller import Seller
from models.users.user import User
from utils.user_utils import is_role from utils.user_utils import is_role
from hashlib import sha512 from hashlib import sha512
# Blueprint to append user endpoints to # Blueprint to append user endpoints to
blueprint = Blueprint("users", __name__, url_prefix="/users") 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 # LOGIN FUNCTIONALITY
@blueprint.route('/login') @blueprint.route('/login')
@ -44,6 +59,62 @@ def login():
return redirect(url_for('main.index')) return redirect(url_for('main.index'))
# SIGNUP FUNCTIONALITY
@blueprint.route('/update/<int:id>')
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", user=user)
@blueprint.post('/update/<int:id>')
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))
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 # SIGNUP FUNCTIONALITY
@blueprint.route('/signup') @blueprint.route('/signup')
def display_signup(): def display_signup():
@ -85,20 +156,10 @@ def signup():
) )
database.create(user) database.create(user)
# Code 307 Preserves the original request (POST) # Code 307 Preserves the original request (POST)
return redirect(url_for('main.users.login'), code=307) return redirect(url_for('main.users.login'), code=307)
# 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'))
# DELETE USER FUNCTIONALITY # DELETE USER FUNCTIONALITY
@blueprint.post('/delete/<int:id>') @blueprint.post('/delete/<int:id>')
def delete(id: int): def delete(id: int):

View File

@ -3,7 +3,16 @@ h2 {
text-align:center; text-align:center;
} }
#input-form-wrap { #form-footer {
background-color: rgba(255, 255, 255, .15);
color:#dfdfdf;
font-size:14px;
width:100%;
padding:10px 0;
border-radius: 0 0 4px 4px;
}
#form-wrapper {
background-color: rgba(255, 255, 255, .15); background-color: rgba(255, 255, 255, .15);
backdrop-filter: blur(200px); backdrop-filter: blur(200px);
width: 35%; width: 35%;
@ -21,14 +30,14 @@ h2 {
gap: 1em; gap: 1em;
} }
.input-form-row { .form-row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-evenly; justify-content: space-evenly;
gap: 1em 1em; gap: 1em 1em;
} }
.input-form-row input, .input-form-row select, .input-form-row option, .input-form-row textarea { .form-row input, .form-row select, .form-row option, .form-row textarea {
width: 100%; width: 100%;
padding: 0 0 0 10px; padding: 0 0 0 10px;
margin: 0; margin: 0;
@ -57,12 +66,12 @@ h2 {
} }
} }
.input-form-row textarea { .form-row textarea {
min-height: 120px; min-height: 120px;
max-width: 100%; max-width: 100%;
} }
.input-form-row input[type="submit"] { .form-row input[type="submit"] {
border: none; border: none;
display:block; display:block;
background-color: rgba(255, 255, 255, .10); background-color: rgba(255, 255, 255, .10);
@ -81,14 +90,6 @@ h2 {
transition: all 0.2s ease; transition: all 0.2s ease;
} }
} }
#create-account-wrap {
background-color: rgba(255, 255, 255, .15);
color:#dfdfdf;
font-size:14px;
width:100%;
padding:10px 0;
border-radius: 0 0 4px 4px;
}
.checkbox { .checkbox {
display: block; display: block;

View File

@ -1,5 +1,5 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/loginform.css') }}" /> <link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}" />
<link rel="stylesheet" href="{{ url_for('static', filename='css/modal.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/modal.css') }}">
<!-- USER MANAGEMENT--> <!-- USER MANAGEMENT-->
@ -26,13 +26,15 @@
<td>{{user.phone}}</td> <td>{{user.phone}}</td>
<td>{{user.role}}</td> <td>{{user.role}}</td>
<td> <td>
<div class="input-form-row"> <div class="form-row">
<a href="{{ url_for('main.users.display_update', id=user.id) }}">
<div class="button neutral"> <div class="button neutral">
<p class="btnText">Edit User</p> <p class="btnText">Edit User</p>
<div class="btnTwo"> <div class="btnTwo">
<p class="btnText2">{{user.id}}</p> <p class="btnText2">{{user.id}}</p>
</div> </div>
</div> </div>
</a>
<label for="deleteModal{{user.id}}"> <label for="deleteModal{{user.id}}">
<div class="button error"> <div class="button error">
<p class="btnText">DELETE USER</p> <p class="btnText">DELETE USER</p>
@ -54,7 +56,7 @@
<h2>Confirm Delete</h2> <h2>Confirm Delete</h2>
<p>Are you sure you want to <b>delete</b> {{user.role}} <b>{{user.username}}</b></p> <p>Are you sure you want to <b>delete</b> {{user.role}} <b>{{user.username}}</b></p>
<form method="POST" action="{{ url_for('main.users.delete', id=user.id) }}"> <form method="POST" action="{{ url_for('main.users.delete', id=user.id) }}">
<div class="input-form-row"> <div class="form-row">
<input type="submit" class="modal-btn error" for="deleteModal{{user.id}}" value="Delete" /> <input type="submit" class="modal-btn error" for="deleteModal{{user.id}}" value="Delete" />
</div> </div>
</form> </form>
@ -92,7 +94,7 @@
<td>{{product.category}}</td> <td>{{product.category}}</td>
<td>{{product.quantityAvailable}}</td> <td>{{product.quantityAvailable}}</td>
<td> <td>
<div class="input-form-row"> <div class="form-row">
<a href="{{url_for('main.products.product', id=product.id)}}"> <a href="{{url_for('main.products.product', id=product.id)}}">
<div class="button neutral"> <div class="button neutral">
<p class="btnText">Edit Product</p> <p class="btnText">Edit Product</p>
@ -122,7 +124,7 @@
<h2>Confirm Delete</h2> <h2>Confirm Delete</h2>
<p>Are you sure you want to <b>delete</b> <b>{{product.name}}</b></p> <p>Are you sure you want to <b>delete</b> <b>{{product.name}}</b></p>
<form method="POST" action="{{ url_for('main.seller.delete', id=product.id) }}"> <form method="POST" action="{{ url_for('main.seller.delete', id=product.id) }}">
<div class="input-form-row"> <div class="form-row">
<input type="submit" class="modal-btn error" for="deleteModal{{product.id}}" value="Delete" /> <input type="submit" class="modal-btn error" for="deleteModal{{product.id}}" value="Delete" />
</div> </div>
</form> </form>

View File

@ -1,22 +1,22 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/loginform.css') }}" /> <link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}" />
<div id="input-form-wrap"> <div id="form-wrapper">
<h2>Login</h2> <h2>Login</h2>
<form class="input-form" method="POST" action="{{ url_for('main.users.login') }}"> <form class="input-form" method="POST" action="{{ url_for('main.users.login') }}">
<div class="input-form-row"> <div class="form-row">
<input type="text" id="username" name="username" placeholder="Username" required> <input type="text" id="username" name="username" placeholder="Username" required>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="password" id="password" name="password" placeholder="Password" required> <input type="password" id="password" name="password" placeholder="Password" required>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="submit" id="login" value="Login"> <input type="submit" id="login" value="Login">
</div> </div>
</form> </form>
<div id="create-account-wrap"> <div id="form-footer">
<p>Not a member? <a href="{{ url_for('main.users.display_signup') }}">Create Account</a><p> <p>Not a member? <a href="{{ url_for('main.users.display_signup') }}">Create Account</a><p>
</div> </div>
</div> </div>

View File

@ -1,18 +1,18 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/loginform.css') }}" /> <link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}" />
<div id="input-form-wrap"> <div id="form-wrapper">
<h2>Create New Product</h2> <h2>Create New Product</h2>
<form class="input-form" method="POST" action="{{ url_for('main.seller.add') }}" enctype="multipart/form-data"> <form class="input-form" method="POST" action="{{ url_for('main.seller.add') }}" enctype="multipart/form-data">
<div class="input-form-row"> <div class="form-row">
<input type="text" id="name" name="name" placeholder="Product Name" required> <input type="text" id="name" name="name" placeholder="Product Name" required>
<input type="file" id="image" name="image" accept="image/x" required> <input type="file" id="image" name="image" accept="image/x" required>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<textarea id="description" name="description" placeholder="Product Description" required></textarea> <textarea id="description" name="description" placeholder="Product Description" required></textarea>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<select name="category" id="category"> <select name="category" id="category">
{% for category in categories %} {% for category in categories %}
<option value="{{category.id}}">{{category.name}}</option> <option value="{{category.id}}">{{category.name}}</option>
@ -20,17 +20,17 @@
</select> </select>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="number" id="cost" name="cost" placeholder="Cost" min=0 step=0.01 required> <input type="number" id="cost" name="cost" placeholder="Cost" min=0 step=0.01 required>
<input type="number" id="quantity" name="quantity" placeholder="Quantity Available" min=0 required> <input type="number" id="quantity" name="quantity" placeholder="Quantity Available" min=0 required>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="submit" id="Create Product" value="Create Product"> <input type="submit" id="Create Product" value="Create Product">
</div> </div>
</form> </form>
<div id="create-account-wrap"> <div id="form-footer">
<p>Want to view all of your products? <a href="{{ url_for('main.seller.display_own') }}">Click Here</a><p> <p>Want to view all of your products? <a href="{{ url_for('main.seller.display_own') }}">Click Here</a><p>
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/products.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/products.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/loginform.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}">
{% if product != None %} {% if product != None %}
{% if user.id == product.sellerID or user.role == "Admin" %} {% if user.id == product.sellerID or user.role == "Admin" %}
@ -7,14 +7,14 @@
<form class="product-fs" method="POST" action="{{ url_for('main.seller.update', id=product.id) }}" enctype="multipart/form-data"> <form class="product-fs" method="POST" action="{{ url_for('main.seller.update', id=product.id) }}" enctype="multipart/form-data">
<img class="product-image" src="{{ url_for('static', filename='assets/img/products/' + product.image) }}" alt="Brake Disks"/> <img class="product-image" src="{{ url_for('static', filename='assets/img/products/' + product.image) }}" alt="Brake Disks"/>
<div class="product-details"> <div class="product-details">
<div class="input-form-row"> <div class="form-row">
<input type="text" id="name" name="name" placeholder="Product Name" value="{{product.name}}" required> <input type="text" id="name" name="name" placeholder="Product Name" value="{{product.name}}" required>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<textarea id="description" name="description" placeholder="Product Description" required>{{product.description}}</textarea> <textarea id="description" name="description" placeholder="Product Description" required>{{product.description}}</textarea>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<select name="category" id="category"> <select name="category" id="category">
{% for category in categories %} {% for category in categories %}
{% if category.id == product.category %} {% if category.id == product.category %}
@ -26,11 +26,11 @@
</select> </select>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="file" id="image" name="image" accept="image/x"> <input type="file" id="image" name="image" accept="image/x">
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="submit" id="Create Product" value="Update Product"> <input type="submit" id="Create Product" value="Update Product">
</div> </div>
@ -44,21 +44,21 @@
</label> </label>
</div> </div>
<div class="product-acquisition-pane"> <div class="product-acquisition-pane">
<div class="input-form-row"> <div class="form-row">
<input type="number" id="cost" name="cost" placeholder="Cost" min=0 step=0.01 value="{{product.cost}}"required> <input type="number" id="cost" name="cost" placeholder="Cost" min=0 step=0.01 value="{{product.cost}}"required>
</div> </div>
<div class="product-delivery">Earliest Delivery Friday 24th December</div> <div class="product-delivery">Earliest Delivery Friday 24th December</div>
<div class="product-postage">+£{{product.cost}} P&P</div> <div class="product-postage">+£{{product.cost}} P&P</div>
<div class="product-stock"> <div class="product-stock">
<div class="input-form-row"> <div class="form-row">
<input type="number" id="quantity" name="quantity" placeholder="Quantity Available" min=0 value="{{product.quantityAvailable}}" required> <input type="number" id="quantity" name="quantity" placeholder="Quantity Available" min=0 value="{{product.quantityAvailable}}" required>
</div> </div>
{% if product.quantityAvailable > 0 %} {% if product.quantityAvailable > 0 %}
<div class="input-form-row"> <div class="form-row">
<div class="product-instock">In Stock</div> <div class="product-instock">In Stock</div>
<div class="product-quantity">{{product.quantityAvailable}} Available</div> <div class="product-quantity">{{product.quantityAvailable}} Available</div>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<a href="{{ url_for('main.stats.view_product_stats', id=product.id) }}"> <a href="{{ url_for('main.stats.view_product_stats', id=product.id) }}">
<div class="button success"> <div class="button success">
<p class="btnText">VIEW STATS</p> <p class="btnText">VIEW STATS</p>
@ -84,7 +84,7 @@
<h2>Confirm Delete</h2> <h2>Confirm Delete</h2>
<p>Are you sure you want to <b>delete {{product.name}}</b> from your products</p> <p>Are you sure you want to <b>delete {{product.name}}</b> from your products</p>
<form method="POST" action="{{ url_for('main.seller.delete', id=product.id) }}"> <form method="POST" action="{{ url_for('main.seller.delete', id=product.id) }}">
<div class="input-form-row"> <div class="form-row">
<input type="submit" class="modal-btn error" for="deleteModal" value="Delete" /> <input type="submit" class="modal-btn error" for="deleteModal" value="Delete" />
</div> </div>
</form> </form>

View File

@ -1,19 +1,19 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/loginform.css') }}" /> <link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}" />
<div id="input-form-wrap"> <div id="form-wrapper">
<h2>Sign Up</h2> <h2>Sign Up</h2>
<form class="input-form" action="{{ url_for('main.users.signup') }}" method="POST"> <form class="input-form" action="{{ url_for('main.users.signup') }}" method="POST">
<div class="input-form-row"> <div class="form-row">
<input type="text" id="firstname" name="firstname" placeholder="First Name" required> <input type="text" id="firstname" name="firstname" placeholder="First Name" required>
<input type="text" id="lastname" name="lastname" placeholder="Last Name" required> <input type="text" id="lastname" name="lastname" placeholder="Last Name" required>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="text" id="username" name="username" placeholder="Username" required> <input type="text" id="username" name="username" placeholder="Username" required>
<input type="email" id="email" name="email" placeholder="Email Address" required> <input type="email" id="email" name="email" placeholder="Email Address" required>
</div> </div>
<div class="input-form-row"> <div class="form-row">
<input type="password" id="password" name="password" minlength=8 placeholder="Password" required> <input type="password" id="password" name="password" minlength=8 placeholder="Password" required>
</div> </div>
@ -22,12 +22,12 @@
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<div class="input-form-row"> <div class="form-row">
<input type="submit" id="Sign Up" value="Sign Up"> <input type="submit" id="Sign Up" value="Sign Up">
</div> </div>
</form> </form>
<div id="create-account-wrap"> <div id="form-footer">
<p>Already have an account? <a href="{{ url_for('main.users.display_login') }}">Login</a><p> <p>Already have an account? <a href="{{ url_for('main.users.display_login') }}">Login</a><p>
</div> </div>
</div> </div>

View File

@ -1,12 +1,12 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/products.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/products.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/stats.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/stats.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/loginform.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}">
<div class="stats"> <div class="stats">
<div> <div>
<canvas id="myChart" width="800px" height="500px"></canvas> <canvas id="myChart" width="800px" height="500px"></canvas>
<br > <br >
<div class="input-form-row"> <div class="form-row">
<a href="?prev_days=7">1 Week</a> <a href="?prev_days=7">1 Week</a>
<a href="?prev_days=14">2 Weeks</a> <a href="?prev_days=14">2 Weeks</a>
<a href="?prev_days=31">1 Month</a> <a href="?prev_days=31">1 Month</a>

44
templates/user.html Normal file
View File

@ -0,0 +1,44 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}" />
<div id="form-wrapper">
<h2>Update User</h2>
{% if user != None %}
<form class="input-form" action="{{ url_for('main.users.update', id=user.id) }}" method="POST">
<div class="form-row">
<input type="text" id="firstname" name="firstname" placeholder="First Name" value="{{user.firstName}}" required>
<input type="text" id="lastname" name="lastname" placeholder="Last Name" value="{{user.lastName}}" required>
</div>
<div class="form-row">
<input type="text" id="username" name="username" placeholder="Username" value="{{user.username}}" required>
<input type="email" id="email" name="email" placeholder="Email Address" value="{{user.email}}" required>
</div>
<div class="form-row">
<input type="tel" id="phone" name="phone" placeholder="Telephone Number" value="{{user.phone}}" required>
</div>
<div class="form-row">
<select name="role" id="role">
{% for role in roles %}
{% if role == user.role %}
<option value="{{role}}" selected>{{role}}</option>
{% else %}
<option value="{{role}}">{{role}}</option>
{% endif%}
{% endfor %}
</select>
</div>
<div class="form-row">
<input type="submit" id="Update" value="Update User">
</div>
</form>
{% else %}
<p>No user found with the given ID.</p>
{% endif %}
<div id="form-footer">
<p>Already have an account? <a href="{{ url_for('main.users.display_login') }}">Login</a><p>
</div>
</div>