From 3b8be99e15837086635696e3bca2a49c97a49a14 Mon Sep 17 00:00:00 2001 From: Luke Else Date: Wed, 14 Feb 2024 21:59:31 +0000 Subject: [PATCH] #10 Added ability to update user details --- controllers/database/user.py | 25 +- controllers/web/user.py | 81 +++++- static/css/{loginform.css => forms.css} | 311 ++++++++++++------------ templates/admin.html | 22 +- templates/login.html | 12 +- templates/new_product.html | 16 +- templates/product.html | 22 +- templates/signup.html | 14 +- templates/stats.html | 4 +- templates/user.html | 44 ++++ 10 files changed, 340 insertions(+), 211 deletions(-) rename static/css/{loginform.css => forms.css} (88%) create mode 100644 templates/user.html diff --git a/controllers/database/user.py b/controllers/database/user.py index 46b7a84..3325cdb 100644 --- a/controllers/database/user.py +++ b/controllers/database/user.py @@ -69,8 +69,29 @@ class UserController(DatabaseController): return self.get_many(query, params) - def update(self): - print("Doing work") + def update(self, user: User): + 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): params = [ diff --git a/controllers/web/user.py b/controllers/web/user.py index 45483f6..3eef393 100644 --- a/controllers/web/user.py +++ b/controllers/web/user.py @@ -7,12 +7,27 @@ 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') @@ -44,6 +59,62 @@ def login(): 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", 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)) + + 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(): @@ -85,20 +156,10 @@ def signup(): ) database.create(user) - # Code 307 Preserves the original request (POST) 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 @blueprint.post('/delete/') def delete(id: int): diff --git a/static/css/loginform.css b/static/css/forms.css similarity index 88% rename from static/css/loginform.css rename to static/css/forms.css index deeff3c..ce7ea5d 100644 --- a/static/css/loginform.css +++ b/static/css/forms.css @@ -1,156 +1,157 @@ -h2 { - font-weight:300; - text-align:center; -} - -#input-form-wrap { - background-color: rgba(255, 255, 255, .15); - backdrop-filter: blur(200px); - width: 35%; - text-align: center; - padding: 1em 0 0 0; - border-radius: 4px; - box-shadow: 0px 30px 50px 0px rgba(0, 0, 0, 0.2); -} - -.input-form { - padding: 1em 2em; - display: flex; - flex-direction: column; - justify-items: center; - gap: 1em; -} - -.input-form-row { - display: flex; - flex-direction: row; - justify-content: space-evenly; - gap: 1em 1em; -} - -.input-form-row input, .input-form-row select, .input-form-row option, .input-form-row textarea { - width: 100%; - padding: 0 0 0 10px; - margin: 0; - color: var(--fg); - border: 1px solid var(--fg); - box-sizing: border-box; - outline: none; - height: 60px; - line-height: 60px; - border-radius: 4px; - font-style: normal; - font-size: 16px; - appearance: none; - position: relative; - display: inline-block; - background: none; - &:focus { - &:invalid { - color: var(--red); - border-color: var(--red); - } - } - - &:valid { - border-color: var(--green); - } -} - -.input-form-row textarea { - min-height: 120px; - max-width: 100%; -} - -.input-form-row input[type="submit"] { - border: none; - display:block; - background-color: rgba(255, 255, 255, .10); - color: var(--fg); - font-weight: bold; - text-transform:uppercase; - cursor: pointer; - transition: all 0.2s ease; - font-size: 18px; - position: relative; - display: inline-block; - cursor: pointer; - text-align: center; - &:hover { - background-color: rgba(255, 255, 255, .20); - 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 { - display: block; - position: relative; - padding-left: 35px; - margin-bottom: 12px; - cursor: pointer; - font-size: 22px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -/* Hide the browser's default checkbox */ -.checkbox input { - position: absolute; - opacity: 0; - cursor: pointer; - height: 0; - width: 0; -} - -/* Create a custom checkbox */ -.checkmark { - position: absolute; - height: 25px; - width: 25px; - background-color: #808080; -} - -/* On mouse-over, add a grey background color */ -.checkbox:hover input ~ .checkmark { - background-color: #ccc; -} - -/* When the checkbox is checked, add a blue background */ -.checkbox input:checked ~ .checkmark { - background-color: #2196F3; -} - -/* Create the checkmark/indicator (hidden when not checked) */ -.checkmark:after { - content: ""; - position: absolute; - display: none; -} - -/* Show the checkmark when checked */ -.checkbox input:checked ~ .checkmark:after { - display: block; -} - -/* Style the checkmark/indicator */ -.checkbox .checkmark:after { - left: 9px; - top: 5px; - width: 5px; - height: 10px; - border: solid white; - border-width: 0 3px 3px 0; - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); +h2 { + font-weight:300; + text-align:center; +} + +#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); + backdrop-filter: blur(200px); + width: 35%; + text-align: center; + padding: 1em 0 0 0; + border-radius: 4px; + box-shadow: 0px 30px 50px 0px rgba(0, 0, 0, 0.2); +} + +.input-form { + padding: 1em 2em; + display: flex; + flex-direction: column; + justify-items: center; + gap: 1em; +} + +.form-row { + display: flex; + flex-direction: row; + justify-content: space-evenly; + gap: 1em 1em; +} + +.form-row input, .form-row select, .form-row option, .form-row textarea { + width: 100%; + padding: 0 0 0 10px; + margin: 0; + color: var(--fg); + border: 1px solid var(--fg); + box-sizing: border-box; + outline: none; + height: 60px; + line-height: 60px; + border-radius: 4px; + font-style: normal; + font-size: 16px; + appearance: none; + position: relative; + display: inline-block; + background: none; + &:focus { + &:invalid { + color: var(--red); + border-color: var(--red); + } + } + + &:valid { + border-color: var(--green); + } +} + +.form-row textarea { + min-height: 120px; + max-width: 100%; +} + +.form-row input[type="submit"] { + border: none; + display:block; + background-color: rgba(255, 255, 255, .10); + color: var(--fg); + font-weight: bold; + text-transform:uppercase; + cursor: pointer; + transition: all 0.2s ease; + font-size: 18px; + position: relative; + display: inline-block; + cursor: pointer; + text-align: center; + &:hover { + background-color: rgba(255, 255, 255, .20); + transition: all 0.2s ease; + } +} + +.checkbox { + display: block; + position: relative; + padding-left: 35px; + margin-bottom: 12px; + cursor: pointer; + font-size: 22px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/* Hide the browser's default checkbox */ +.checkbox input { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; +} + +/* Create a custom checkbox */ +.checkmark { + position: absolute; + height: 25px; + width: 25px; + background-color: #808080; +} + +/* On mouse-over, add a grey background color */ +.checkbox:hover input ~ .checkmark { + background-color: #ccc; +} + +/* When the checkbox is checked, add a blue background */ +.checkbox input:checked ~ .checkmark { + background-color: #2196F3; +} + +/* Create the checkmark/indicator (hidden when not checked) */ +.checkmark:after { + content: ""; + position: absolute; + display: none; +} + +/* Show the checkmark when checked */ +.checkbox input:checked ~ .checkmark:after { + display: block; +} + +/* Style the checkmark/indicator */ +.checkbox .checkmark:after { + left: 9px; + top: 5px; + width: 5px; + height: 10px; + border: solid white; + border-width: 0 3px 3px 0; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); } \ No newline at end of file diff --git a/templates/admin.html b/templates/admin.html index d4cbc3f..01b46f1 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -1,5 +1,5 @@ - + @@ -26,13 +26,15 @@ {{user.phone}} {{user.role}} -
-
-

Edit User

-
-

{{user.id}}

+ +