From c65748a50f887bb8451aeb1ee0489d534cdc6e43 Mon Sep 17 00:00:00 2001
From: Ethan-clay03 <ethanclay2017@gmail.com>
Date: Sun, 5 Jan 2025 18:25:24 +0000
Subject: [PATCH] Carry on quandary page, look to begin adding admin role and
 adding/removing booking listings

---
 app/errors/routes.py               |  5 ++-
 app/profile/routes.py              | 61 ++++++++++++++++++++++--------
 app/templates/base.html            |  1 +
 app/templates/errors/quandary.html |  4 +-
 app/templates/profile/signup.html  |  9 +++--
 5 files changed, 57 insertions(+), 23 deletions(-)

diff --git a/app/errors/routes.py b/app/errors/routes.py
index 14aeca0..3581bd0 100644
--- a/app/errors/routes.py
+++ b/app/errors/routes.py
@@ -1,8 +1,9 @@
-#https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login#step-1-installing-packages
 from flask import render_template, session
 from app.errors import bp
 
 @bp.route('/quandary')
 def quandary():
-    error_message = session.pop('error_message')
+    error_message = 'Something unexpected occurred.'
+    if 'error_message' in session:
+        error_message = session.pop('error_message')
     return render_template("errors/quandary.html", error_message=error_message)
diff --git a/app/profile/routes.py b/app/profile/routes.py
index 3fa2fa8..bd6df04 100644
--- a/app/profile/routes.py
+++ b/app/profile/routes.py
@@ -16,18 +16,19 @@ def signup():
             'password': request.form.get('password')
         }
 
-        if not form_data['username'] or not form_data['email'] or not form_data['password']:
-            flash('Missing required fields: Email, Username, Password')
-            return redirect(url_for('profile.signup'))
-
-        user = User.query.filter_by(email=form_data['email']).first()
-
-        if user:
-            flash('Email address already exists')
+        # Validate form data
+        error = validate_signup_form(form_data)
+        if error:
+            flash(error)
             return redirect(url_for('profile.signup'))
 
+        # Create new user and log in automatically
         try:
-            new_user = User.create_user(username=form_data['username'], email=form_data['email'], password=form_data['password'])
+            new_user = User.create_user(
+                username=form_data['username'],
+                email=form_data['email'],
+                password=form_data['password']
+            )
             db.session.add(new_user)
             db.session.commit()
 
@@ -40,14 +41,36 @@ def signup():
 
     return render_template('profile/signup.html')
 
+def validate_signup_form(form_data):
+    if not all(form_data.values()):
+        return 'Missing required fields: Email, Username, Password'
+
+    if not is_valid_username(form_data['username']):
+        return "You are only allowed to use the following special characters in usernames: - _ +"
+
+    if User.search_user_by_email(form_data['email']):
+            return'Email address already exists'
+
+    if User.search_user_by_username(form_data['username']):
+        return 'Username already exists'
+    
+    return None
+
+def is_valid_username(username):
+    allowed_special_chars = "-_+"
+    return all(c.isalnum() or c in allowed_special_chars for c in username)
+
 
 @bp.route('/login', methods=['POST'])
 def login_post():
-    email = request.form.get('email')
+    username_field = request.form.get('username')
     password = request.form.get('password')
     remember = True if request.form.get('remember') else False # Change to boolean value depending if tickbox is selected
 
-    user = User.query.filter_by(email=email).first()
+    if '@' in username_field:
+        user = User.search_user_by_email(username_field)
+    else:
+        user = User.search_user_by_username(username_field)
 
     if not user or not check_password_hash(user.password, password):
         flash('Please check your login details and try again.')
@@ -64,24 +87,30 @@ def check_username():
     if username is None:
         return jsonify({'error': 'Username is required'}), 400
     
+    if not is_valid_username(username):
+        return jsonify({'error': "Username contains invalid special characters. You may only use: - _ +"}), 400
     #Search to see if username already exists
     user_exist = User.search_user_by_username(username)
     if user_exist is not None:
         return jsonify({'error': 'Username already exists'}), 400
 
-    return jsonify({'available': True, 'success': username + 'is available.'})
+    return jsonify({'available': True, 'success': username + ' is available.'})
 
 
 @bp.route('/check-email', methods=['POST'])
 def check_email():
     data = request.get_json()
     email = data.get('email', '').strip()
-    
-    if not email:
+
+    if email is None:
         return jsonify({'error': 'Email is required'}), 400
+    
+    email_exist = User.search_user_by_email(email)
+
+    if email_exist:
+        return jsonify({'error': 'Email already registered'}), 400
 
-    is_available = email not in emails
-    return jsonify({'available': is_available})
+    return jsonify({'available': True, 'success': 'Email is available'})
 
 
 @bp.route('/logout')
diff --git a/app/templates/base.html b/app/templates/base.html
index 5bb63ea..5f4c7ab 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -43,6 +43,7 @@
                                         <li><a class="dropdown-item" href="{{ url_for('profile.manage_bookings')}}">My Bookings</a></li>
                                         <li><a class="dropdown-item" href="{{ url_for('profile.logout') }}">Log Out</a></li>
                                     {% else %}
+                                        <li><a class="dropdown-item" href="{{ url_for('profile.signup') }}">Sign Up</a></li>
                                         <li><a class="dropdown-item" href="{{ url_for('profile.login') }}">Log In</a></li>
                                     {% endif %}
                                 </ul>
diff --git a/app/templates/errors/quandary.html b/app/templates/errors/quandary.html
index 7cb8f82..1fd93fe 100644
--- a/app/templates/errors/quandary.html
+++ b/app/templates/errors/quandary.html
@@ -6,7 +6,7 @@
 <div class="quandary-div">
     <h1>500 Server Error</h1>
     <div class="container">
-      <div style="margin-bottom: 20px;"><span>Something went wrong, if this continues please contact support</span></div>
+      <div><span>Something went wrong, if this continues please contact support</span></div>
       <div class="button_2"><i class="fa-solid fa-circle-arrow-left"></i><span> Go back</span></div>
     </div>
 </div>
@@ -16,7 +16,7 @@
 .quandary-div {
   height: 100vh;
   display: flex;
-  flex-direction: row;
+  flex-direction: column;
   justify-content: center;
   align-items: baseline;
   align-content: center;
diff --git a/app/templates/profile/signup.html b/app/templates/profile/signup.html
index 7f03243..2530bb5 100644
--- a/app/templates/profile/signup.html
+++ b/app/templates/profile/signup.html
@@ -49,10 +49,10 @@
                 .then(response => response.json())
                 .then(data => {
                     if (data.available) {
-                        feedbackElement.textContent = `${field.charAt(0).toUpperCase() + field.slice(1)} is available.`;
+                        feedbackElement.textContent = data.success;
                         feedbackElement.style.color = 'green';
                     } else {
-                        feedbackElement.textContent = `${field.charAt(0).toUpperCase() + field.slice(1)} is already taken.`;
+                        feedbackElement.textContent = data.error;
                         feedbackElement.style.color = 'red';
                     }
                 })
@@ -84,7 +84,10 @@
     }, 500));
 
     document.getElementById('email').addEventListener('input', delayAvailabilityCheck(function () {
-        checkEmailAvailability(this.value);
+        const emailValue = this.value;
+        if (emailValue.includes('@') && emailValue.includes('.')) {
+            checkEmailAvailability(this.value);
+        }
     }, 500));
 
 </script>
-- 
GitLab