diff --git a/requirements.txt b/requirements.txt index b2c7d6208a05cb7e80273d2aa9d32bd2964d7f3e..e9dbd773c1609b7758d260c4e90c238767d675aa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ Flask_WTF WTForms flask_login flask_mail -black \ No newline at end of file +requests +black diff --git a/seed_database.py b/seed_database.py index 6ed51f0bcb08864afbe839037459a1966c2aaa3b..00d1058e6dbd6cdc57ec8cc4d00d03592262f3d3 100644 --- a/seed_database.py +++ b/seed_database.py @@ -71,7 +71,6 @@ with app.app_context(): password="password", email="admin@website.com", phone_number="8383838", - securityQ1="rainbow", ) user.userType = "admin" # Because of how flasks works, once a row is created it can be further altered via its objects and changes saved on db.session.commit(). diff --git a/store/forms.py b/store/forms.py index 6a77bfb8def0a0afd68452e459206818213c3873..164439f0f81a39623e157295b2d08d65217c377e 100644 --- a/store/forms.py +++ b/store/forms.py @@ -15,6 +15,7 @@ from wtforms import ( class RegistrationForm(FlaskForm): +<<<<<<< HEAD username = StringField( "Username", [validators.DataRequired(), validators.Length(max=256)] ) @@ -26,6 +27,11 @@ class RegistrationForm(FlaskForm): [validators.DataRequired(), validators.Length(max=30)], ) phone_number = TelField("Phone Number", [validators.DataRequired()]) +======= + username = StringField("Username", [validators.Length(min=4, max=255)]) + email = StringField("Email Address", [validators.Length(min=6, max=255)]) + phone_number = StringField("Phone Number", [validators.Length(min=6, max=35)]) +>>>>>>> master password = PasswordField( "New Password", [ @@ -45,9 +51,14 @@ class RegistrationForm(FlaskForm): class LoginForm(FlaskForm): +<<<<<<< HEAD username = StringField("Username") password = PasswordField("Password") securityQ1 = StringField("Enter your Favourite Colour", [validators.Length(max=30)]) +======= + username = StringField("Username", [validators.Length(min=4, max=255)]) + password = PasswordField("Password", [validators.Length(min=6, max=220)]) +>>>>>>> master submit = SubmitField("Login", render_kw={"class": "button"}) diff --git a/store/models.py b/store/models.py index 92abb7ba28addf75be728c2a3a951329d69beccb..ce39bbdb4be2a9a1a177d0671ccd9cb682e0a837 100644 --- a/store/models.py +++ b/store/models.py @@ -91,7 +91,6 @@ class User(db.Model, UserMixin): # as the password itself can be of a theoretically infinite length but hashed # into a sepcific size. password_hash = db.Column(db.String(256), nullable=False) - securityQ1 = db.Column(db.String(30), nullable=False) userType = db.Column(db.String(20), default="standard") @classmethod @@ -101,7 +100,6 @@ class User(db.Model, UserMixin): password: str, email: str, phone_number: str, - securityQ1: str, ): password_hash = generate_password_hash(password) user = cls( @@ -109,7 +107,6 @@ class User(db.Model, UserMixin): password_hash=password_hash, email=email, phone_number=phone_number, - securityQ1=securityQ1, ) db.session.add(user) db.session.commit() @@ -122,12 +119,6 @@ class User(db.Model, UserMixin): user.password_hash = password_hash db.session.commit() - @classmethod - def update_security_q1(cls, user_id: int, securityQ1: str): - user = cls.query.get(user_id) - user.securityQ1 = securityQ1 - db.session.commit() - @classmethod def update_username(cls, user_id: int, username: str): user = cls.query.get(user_id) @@ -159,12 +150,6 @@ class User(db.Model, UserMixin): def check_password(self, password: str) -> bool: return check_password_hash(self.password_hash, password) - def securityverification(self, securityQ1: str) -> bool: - if self.securityQ1 == securityQ1: - return True - else: - return False - def checkIfUserExist(self, username: str) -> bool: if self.username == username: return True diff --git a/store/routes.py b/store/routes.py index 7d0bfc98b70cf35c4e73fa8b8834082bc445b4b8..cb39c22a6bbc7eafbbc40a15a995474892a05636 100644 --- a/store/routes.py +++ b/store/routes.py @@ -9,6 +9,20 @@ from flask import ( session, abort, ) +from flask_wtf import FlaskForm +from flask_wtf.csrf import generate_csrf +import requests +import datetime +import re +from wtforms import ( + Form, + StringField, + validators, + SelectField, + TextAreaField, + ValidationError, + HiddenField, +) import json from store.utility import * from store.forms import * @@ -71,22 +85,6 @@ def index(): return render_template("index.html", title="Home", repositories=repositories) -@app.route("/basket") -def basket(): - items = [] - total_price = 0 - if "basket" not in session: - session["basket"] = {} - else: - for item_id, item in session["basket"].items(): - items.append(item) - total_price = total_price + item["price"] - print(session["basket"]) - return render_template( - "basket.html", title="Basket", items=items, total_price=total_price - ) - - @app.route("/items") def items(): unsold_items = get_unsold_items() @@ -122,14 +120,19 @@ def item_set_page(item_id): def register(): form = RegistrationForm() if form.validate_on_submit(): - flash("RAN") - user = User.create_user( - form.username.data, - form.password.data, - form.email.data, - form.phone_number.data, - form.securityQ1.data, - ) + if User.checkIfUserExist(User, form.username.data): + error = "The username you chose is already taken." + return render_template( + "userContent/register.html", title="Register", error=error + ) + + else: + user = User.create_user( + form.username.data, + form.password.data, + form.email.data, + form.phone_number.data, + ) return redirect(url_for("index")) return render_template("userContent/register.html", form=form) @@ -141,15 +144,14 @@ def login(): if form.validate_on_submit(): username = form.username.data password = form.password.data - securityQ1 = form.securityQ1.data user = User.query.filter_by(username=username).first() + print("hi") if user and user.check_password(password): - if user.securityverification(securityQ1) == True: - login_user(user) - print(current_user.userType) - return redirect(url_for("index")) - else: - flash("Invalid security answer") + print("success") + login_user(user) + print(current_user.userType) + return redirect(url_for("index")) + else: flash("Login unsuccessful. Please check username and password.") return render_template("userContent/login.html", form=form) @@ -270,24 +272,6 @@ def verify_code_security1(): return render_template("userContent/verify_code_security1.html") -@app.route("/verify_code_security1_confirm", methods=["GET", "POST"]) -def verify_code_security1_confirm(): - if "user_id" not in session: - return redirect(url_for("reset_security1")) - user_id = session["user_id"] - if request.method == "POST": - securityQ1 = request.form["securityQ1"] - confirm_securityQ1 = request.form["confirm_securityQ1"] - if securityQ1 == confirm_securityQ1: - User.update_security_q1(user_id, securityQ1) - session.pop("user_id", None) - flash("Your security question has been successfully reset") - return redirect(url_for("login")) - else: - flash("security question do not match") - return render_template("userContent/verify_code_security1_confirm.html") - - @app.route("/account") @login_required def account(): @@ -470,17 +454,11 @@ def ChangeUsername(): if request.method == "POST": user_id = current_user.user_id password = request.form["password"] - securityQ1 = request.form["securityQ1"] NewUsername = request.form["NewUsername"] user = User.query.get(user_id) if user and user.check_password(password): - # if User.check_password(user_id, password): - if user.securityverification(securityQ1) == True: - User.update_username(user_id, NewUsername) - flash("username successfully changed.") - - else: - flash("Invalid security answer") + User.update_username(user_id, NewUsername) + flash("username successfully changed.") else: flash("Wrong password.") @@ -493,17 +471,11 @@ def ChangeEmail(): if request.method == "POST": user_id = current_user.user_id password = request.form["password"] - securityQ1 = request.form["securityQ1"] + NewEmail = request.form["NewEmail"] user = User.query.get(user_id) if user and user.check_password(password): - # if User.check_password(user_id, password): - if user.securityverification(securityQ1) == True: - User.update_email(user_id, NewEmail) - flash("email successfully changed.") - - else: - flash("Invalid security answer") + User.update_email(user_id, NewEmail) else: flash("Wrong password.") @@ -516,23 +488,147 @@ def ChangePhNumber(): if request.method == "POST": user_id = current_user.user_id password = request.form["password"] - securityQ1 = request.form["securityQ1"] NewNumber = request.form["NewNumber"] user = User.query.get(user_id) if user and user.check_password(password): - # if User.check_password(user_id, password): - if user.securityverification(securityQ1) == True: - User.update_Number(user_id, NewNumber) - flash("New Number successfully changed.") - - else: - flash("Invalid security answer") + User.update_Number(user_id, NewNumber) + flash("New Number successfully changed.") else: flash("Wrong password.") return render_template("userContent/ChangePhNumber.html") +def validate_cvv_2(form, field): + regex = "^[0-9]{3,4}$" + p = re.compile(regex) + if not re.search(p, field.data): + raise ValidationError("CVV2 is incorrect") + + +def validate_address(form, field): + # Uses the google maps geocoding api to check if a postcode or address exists + + url = "https://maps.googleapis.com/maps/api/geocode/json" + + api_key = "AIzaSyCz4xyIl5yaIg869orL07ye2ainw7kv5Pc" + + params = {"address": field, "key": api_key} + + response = requests.get(url, params=params).json() + + # Check if response status is "OK" and has at least one result + if response["status"] == "OK" and len(response["results"]) > 0: + print("Valid address or postcode") + pass + else: + raise ValidationError("Enter valid address") + + +class CheckoutForm(Form): + months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + today = datetime.date.today() + year = int(today.year) + years = [year] + for year in range(year, year + 50, 1): + years.append(year) + name = StringField( + "Name on card", [validators.Length(min=2, max=30), validators.DataRequired()] + ) + card_number = StringField( + "Card Number", [validators.Length(min=15, max=16), validators.DataRequired()] + ) + exp_date_month = SelectField("Month", [validators.DataRequired()], choices=months) + exp_date_year = SelectField("Year", [validators.DataRequired()], choices=years) + cvv_2 = StringField( + "CVV2", + [validators.Length(min=3, max=4), validators.DataRequired(), validate_cvv_2], + ) + address = TextAreaField( + "Address", + [ + validators.Length(min=10, max=250), + validators.DataRequired(), + validate_address, + ], + ) + postcode = StringField( + "Postcode", + [ + validators.Length(min=6, max=10), + validators.DataRequired(), + validate_address, + ], + ) + # Cross-site request forgery token to make sure requests are sent from our site + csrf_token = HiddenField() + + +@app.route("/order_summary") +def order_summary(): + total_price = 0 + items = [] + if "basket" in session: + address = session.get("address", "") + for item_id, item in session["basket"].items(): + + items.append(item) + total_price = total_price + item["price"] + session.clear() + + return render_template( + "order_summary.html", items=items, address=address, total_price=total_price + ) + else: + return redirect(url_for("index")) + + +@app.route("/checkout", methods=["POST", "GET"]) +def checkout(): + items = [] + total_price = 0 + form = CheckoutForm(request.form) + # Get items stored in basket and add to list + for item_id, item in session["basket"].items(): + items.append(item) + total_price = total_price + item["price"] + if request.method == "POST" and form.validate(): + session["address"] = str(form.address.data + ", " + form.postcode.data) + try: + for item_id, item, is_item_set in session["basket"]: + if is_item_set == True: + sell_item(get_item_set_by_id(item_id)) + else: + sell_item(get_item_by_id(item_id)) + return redirect(url_for("order_summary")) + except: + flash("One or more items in basket have already been sold!") + csrf_token = generate_csrf() + return render_template( + "checkout.html", + form=form, + total_price=total_price, + csrf_token=csrf_token, + items=items, + ) + + +@app.route("/basket") +def basket(): + items = [] + total_price = 0 + if "basket" not in session: + session["basket"] = {} + else: + for item_id, item in session["basket"].items(): + items.append(item) + total_price = total_price + item["price"] + + return render_template( + "basket.html", title="Basket", items=items, total_price=total_price + ) + + @app.route("/add_to_basket", methods=["POST"]) def add_to_basket(): item_id = request.form["item_id"] @@ -543,6 +639,7 @@ def add_to_basket(): "id": item_obj.id, "description": item_obj.description, "price": item_obj.price, + "is_item_set" : False } if "basket" not in session: session["basket"] = {} @@ -552,7 +649,7 @@ def add_to_basket(): else: session["basket"][item_id] = item_dict flash("Item added to basket: " + item_obj.description) - print(session["basket"]) + return redirect(url_for("item_page", item_id=item_id)) @@ -565,7 +662,8 @@ def add_to_basket_set(): item_dict = { "id": item_obj.id, "description": item_obj.description, - "price": item_obj.price, + "price": item_obj.price, + "is_item_set" : True } if "basket" not in session: session["basket"] = {} diff --git a/store/static/_main.css b/store/static/_main.css index 1b3d82142cf2c47ca433a30ca35415d659e66c09..3c7a383afee99080e608796f06820a46ff9453fa 100644 --- a/store/static/_main.css +++ b/store/static/_main.css @@ -32,8 +32,167 @@ display: flex; } +<<<<<<< HEAD /* Moves the entire line smoothly to the left. */ .carousel-inner .carousel-item-end, .carousel-inner .carousel-item-start { transform: translateX(0); +======= +@media only screen and (min-width: 768px) { + .col-1 { + width: 8.33%; + } + + .col-2 { + width: 16.66%; + } + + .col-3 { + width: 25%; + } + + .col-4 { + width: 33.33%; + } + + .col-5 { + width: 41.66%; + } + + .col-6 { + width: 50%; + } + + .col-7 { + width: 58.33%; + } + + .col-8 { + width: 66.66%; + } + + .col-9 { + width: 75%; + } + + .col-10 { + width: 83.33%; + } + + .col-11 { + width: 91.66%; + } + + .col-12 { + width: 100%; + } +} + +.content { + /* to stop content being hidden by the fixed footer */ + padding-bottom: 100px; +} + +body { + line-height: 1; +} + +ol, +ul { + list-style: none; +} + +blockquote, +q { + quotes: none; +} + +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} + +/* table { + border-collapse: collapse; + border-spacing: 0; +} */ + + +/* End of resetting */ + + +footer { + background-color: black; + color: white; + position: fixed; + bottom: 0; + left: 0; + width: 100%; +} + + + + +.navbar li a { + color: white; + display: block; + text-align: center; + text-decoration: none; + padding: 14px 16px; +} + +.navbar ul { + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; + background-color: black; +} + + +input[type=text] { + float: left; + padding: 6px; + border: none; + margin-top: 8px; + margin-right: 16px; + font-size: 17px; +} + +.navbar li { + float: left; +} + +.navbar li a:hover { + background-color: white; + color: black; +} + +* { + text-align: center; + font-family: sans-serif; +} + +h1 { + color: black; + font-size: 30px; +} + +.error { + text-decoration: none; + color: red; + font-size: 30px; +} + +li { + list-style-type: none; +} + +.loginTable { + margin-left: auto; + margin-right: auto; +>>>>>>> master } \ No newline at end of file diff --git a/store/templates/basket.html b/store/templates/basket.html index c20dcf34c3bc4f3ec1a9938b62924e5be6f0ea23..dc0077cbfd3398a07d52787d2187f271053fe615 100644 --- a/store/templates/basket.html +++ b/store/templates/basket.html @@ -1,11 +1,51 @@ {% extends "base.html" %} {% block content %} +<<<<<<< HEAD <div class="container"> <h1>Basket</h1> {% if items %} <table class="table"> <thead class="text-light" style="background-color: #000000"> +======= +<h1>Basket</h1> +<style> + table { + border-collapse: collapse; + width: 100%; + } + + th, + td { + text-align: left; + padding: 8px; + border-bottom: 1px solid #ddd; + } + + th { + background-color: #000000; + color: white; + } + + .remove-button { + background-color: #f44336; + color: white; + border: none; + padding: 8px 16px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + margin: 4px 2px; + cursor: pointer; + } +</style> + +{% if items %} +<div> + <table> + <thead> +>>>>>>> master <tr> <th>Item description</th> <th>Item price</th> @@ -20,13 +60,21 @@ <td> <form method="POST" action="/remove_item"> <input type="hidden" name="item" value="{{ item['id'] }}"> +<<<<<<< HEAD <input type="submit" value="Remove" class="btn btn-danger"> +======= + <input type="submit" value="Remove"> +>>>>>>> master </form> </td> </tr> {% endfor %} </tbody> +<<<<<<< HEAD <tfoot style="background-color: #f2f2f2"> +======= + <tfoot> +>>>>>>> master <tr> <td>Total price:</td> <td>£{{ total_price }}</td> @@ -34,8 +82,17 @@ </tr> </tfoot> </table> +<<<<<<< HEAD {% else %} <p>Your basket is empty.</p> {% endif %} </div> +======= + <a href="{{url_for('checkout', total_price = total_price)}}">Checkout</a> +</div> +{% else %} +<p>Your basket is empty.</p> +{% endif %} + +>>>>>>> master {% endblock %} \ No newline at end of file diff --git a/store/templates/checkout.html b/store/templates/checkout.html new file mode 100644 index 0000000000000000000000000000000000000000..bbd426d5772a66927fa6d8616c83173b108967c1 --- /dev/null +++ b/store/templates/checkout.html @@ -0,0 +1,114 @@ +{% extends 'base.html' %} + +{% block title %} Checkout {% endblock %} + +{% block content %} + +<style> + h1 { + padding: 15px; + } + + .grid-container-element { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 20px; + width: 90%; + padding: 10px; + } + + .grid-child-element { + margin: 10px; + padding: 10px; + } + + form { + display: flex; + flex-direction: column; + align-items: center; + } + + label { + display: inline-block; + width: 150px; + text-align: left; + margin-right: 10px; + padding: 5px; + } + + input[type="text"], + select { + margin-left: 10px; + outline: none; + padding: 5px; + border: 1px solid gray; + } + + table { + border-collapse: collapse; + width: 100%; + } + + th, + td { + text-align: left; + padding: 8px; + border-bottom: 1px solid #ddd; + } + + th { + background-color: #000000; + color: white; + } +</style> +<div class="grid-container-element"> + <div class="grid-child-element"> + <h1>Checkout</h1> + <form method='POST' class="content"> + {{ form.csrf_token }} + <br /> + <label for="name">{{ form.name.label }}{{ form.name }}</label><br /> + <br /> + <label for="card_number">{{ form.card_number.label }}{{ form.card_number }}</label><br /> + <br /> + <label for="exp_date_month">{{ form.exp_date_month.label }}{{ form.exp_date_month }}</label> + <label for="exp_date_year">{{ form.exp_date_year.label }}{{ form.exp_date_year }}</label><br /> + <br /> + <label for="cvv_2">{{ form.cvv_2.label }}{{ form.cvv_2 }}</label><br /> + <br /> + <label for="address">{{form.address.label}}{{form.address}}</label><br /> + <br /> + <label for="postcode">{{form.postcode.label}}{{form.postcode}}</label><br /> + <br /> + <p><input type="submit" value="Complete payment"></p> + </form> + </div> + <div class="grid-child-element"> + <h1>Order Summary</h1> + <table class="content"> + <thead> + <tr> + <th>Item description</th> + <th>Item price</th> + <th></th> + </tr> + </thead> + <tbody> + {% for item in items %} + <tr> + <td>{{ item['description'] }}</td> + <td>£{{ item['price'] }}</td> + </tr> + {% endfor %} + </tbody> + <tfoot> + <tr> + <td>Total price:</td> + <td>£{{ total_price }}</td> + <td></td> + </tr> + </tfoot> + </table> + </div> +</div> +{% endblock %} \ No newline at end of file diff --git a/store/templates/items.html b/store/templates/items.html index c67c840de60d104f7506362f59c88fa6405eecfb..3b67af7685f3d2f6cc98654881bb795e27a8ce6f 100644 --- a/store/templates/items.html +++ b/store/templates/items.html @@ -1,5 +1,6 @@ {%extends 'base.html' %} {% block title %} Items | Antiques Online {% endblock %} +<<<<<<< HEAD {% block content %} <!-- https://getbootstrap.com/docs/4.0/layout/grid/ --> <div class="container pb-3"> @@ -24,6 +25,51 @@ {% else %} <p>No items available</p> {% endif %} +======= +<style> + .grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + grid-gap: 10px; + grid-auto-rows: minmax(100px, auto); + padding-bottom: 100px; + } + + .grid-item { + grid-row: span 1; + grid-column: span 1; + padding: 10px; + } + + .grid-item img { + max-width: 100%; + height: auto; + } + + .grid-item h2 { + margin: 10px 0; + font-size: 18px; + + } + + .grid-item p { + margin: 5px 0; + font-size: 14px; + } +</style> + +<div class="grid"> + {% if items %} + {% for item in items %} + <div class="grid-item"> + + <img src="static\image_placeholder.png" alt="{{ item.description }}"> + <h2>{{ item.description }}</h2> + <p>£{{ item.price }}</p> + <a href="{{url_for('item_page', item_id = item.id)}}">View + Details</a> + +>>>>>>> master </div> </div> {% endblock %} \ No newline at end of file diff --git a/store/templates/order_summary.html b/store/templates/order_summary.html new file mode 100644 index 0000000000000000000000000000000000000000..579a91d99ba262f62680d09adc8c6776d7281fc3 --- /dev/null +++ b/store/templates/order_summary.html @@ -0,0 +1,72 @@ +{%extends 'base.html' %} + +{% block title %} Order Summary {% endblock %} + +{% block content %} +<!DOCTYPE html> +<html> + +<head> + <title>Order Summary</title> + <style> + h1 { + margin-top: 0; + } + + table { + width: 100%; + border-collapse: collapse; + margin-top: 20px; + } + + table th, + table td { + padding: 8px; + text-align: left; + border-bottom: 1px solid #ddd; + } + + .total { + font-weight: bold; + } + + .address { + margin-top: 20px; + } + </style> +</head> + +<body class="content"> + <h1>Order Summary</h1> + + <table> + <thead> + <tr> + <th>Item</th> + <th>Price</th> + </tr> + </thead> + <tbody> + {% for item in items %} + <tr> + <td>{{ item["description"] }}</td> + <td>£{{ item["price"] }}</td> + </tr> + {% endfor %} + <tr class="total"> + <td>Total:</td> + <td>£{{ total_price }}</td> + </tr> + </tbody> + </table> + + <div class="address"> + <h2>Delivery Address</h2> + <p>{{ address }}</p> + </div> +</body> + +</html> + + +{% endblock %} \ No newline at end of file diff --git a/store/templates/userContent/ChangeEmail.html b/store/templates/userContent/ChangeEmail.html index 286607e15a5f3ae62959e4d623c44a6dcd9d5bea..2a1e2814ef2e8e272b905573b9bc5cfe2354f133 100644 --- a/store/templates/userContent/ChangeEmail.html +++ b/store/templates/userContent/ChangeEmail.html @@ -8,10 +8,6 @@ <label for="password"><b>Password verification</b></label> <input type="password" placeholder="Enter Password" name="password" id="password" required> - - <label for="securityQ1"><b>what is your favourite colour, for verification porpuses/b></label> - <input type="securityQ1" placeholder="Enter a colour" name="securityQ1" id="securityQ1" required> - <label for="NewEmail"><b>New E-mail</b></label> <input type="NewEmail" placeholder="Enter new E-mail" name="NewEmail" id="NewEmail" required> diff --git a/store/templates/userContent/ChangePhNumber.html b/store/templates/userContent/ChangePhNumber.html index ed35cc62e5f7359ea8c199afc4d45afae1ecf557..76ec481786f40b2e0feaa19de551ad806f5e7389 100644 --- a/store/templates/userContent/ChangePhNumber.html +++ b/store/templates/userContent/ChangePhNumber.html @@ -9,9 +9,6 @@ <input type="password" placeholder="Enter Password" name="password" id="password" required> - <label for="securityQ1"><b>what is your favourite colour, for verification porpuses/b></label> - <input type="securityQ1" placeholder="Enter a colour" name="securityQ1" id="securityQ1" required> - <label for="NewNumber"><b> Enter New Number</b></label> <input type="NewNumber" placeholder="Enter new Number" name="NewNumber" id="NewNumber" required> diff --git a/store/templates/userContent/ChangeUsername.html b/store/templates/userContent/ChangeUsername.html index d576cad986a38723a3e0fa2cb1504e26c238d80c..155155bb76accf9fbcc413266f64ac21d79ea792 100644 --- a/store/templates/userContent/ChangeUsername.html +++ b/store/templates/userContent/ChangeUsername.html @@ -9,8 +9,6 @@ <input type="password" placeholder="Enter Password" name="password" id="password" required> - <label for="securityQ1"><b>what is your favourite colour, for verification porpuses/b></label> - <input type="securityQ1" placeholder="Enter a colour" name="securityQ1" id="securityQ1" required> <label for="NewUsername"><b>New username</b></label> <input type="NewUsername" placeholder="Enter new Username" name="NewUsername" id="NewUsername" required> diff --git a/store/templates/userContent/login.html b/store/templates/userContent/login.html index 7744afe29955c2368fb8ded00fd070e44f7a9cdb..54e40a8c46fe02238084b772139265c3ee2b1a6e 100644 --- a/store/templates/userContent/login.html +++ b/store/templates/userContent/login.html @@ -2,6 +2,7 @@ {%extends 'base.html' %} {% block title %} Login | Antiques Online {% endblock %} {% block content %} +<<<<<<< HEAD <div class="container d-flex align-items-center justify-content-center"> <div class="my-4 w-25"> <h1>Login</h1> @@ -13,5 +14,28 @@ {{form.submit(class="btn btn-primary")}} </form> </div> +======= +<br> +<h1>Login</h1> +<br> +<div class="container"> + <form method="POST"> + {{form.hidden_tag()}} + <dl> + <table class="loginTable"> + <tr> + <td>{{ render_field(form.username) }} </td> + </tr> + <td>{{ render_field(form.password) }}</td> + </tr> + </table> + </dl> + <br> + {{form.submit()}} + <br> + </form> + <td><a href="{{ url_for('reset_password')}}">I Forgot my Password!</a></td><br><br> + <br> +>>>>>>> master </div> {% endblock %} \ No newline at end of file diff --git a/store/utility.py b/store/utility.py index a7e9fea0bd3f0752f176913bbf96c86988410183..8029ff9f8a9c6c99dbad6313104db14acb3d95e6 100644 --- a/store/utility.py +++ b/store/utility.py @@ -1,6 +1,7 @@ # TODO: Search for similiarly named item to replace removed item from itemset. from difflib import SequenceMatcher +from wtforms import ValidationError from store.models import * from sqlalchemy import select, func import datetime @@ -152,3 +153,7 @@ def update_set(reference_item): itemset.items.remove(reference_item) itemset.items.append(similar_items[0]) db.session.commit() + + +def get_item_by_id(id): + return Item.query.get(id)