Skip to content

Commit

Permalink
Get signup working and login working cleanly.
Browse files Browse the repository at this point in the history
  • Loading branch information
witbrock committed Oct 5, 2024
1 parent 4e25c02 commit 7649bfb
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 13 deletions.
Binary file modified src/web_interface/__pycache__/user_data.cpython-312.pyc
Binary file not shown.
69 changes: 62 additions & 7 deletions src/web_interface/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
from flask import Flask, render_template, redirect, url_for, request
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_pymongo import PyMongo
from web_interface.user_data import VonUser # work our why it doesn't like this import when it's in the same directory

from werkzeug.security import generate_password_hash, check_password_hash
from bson.objectid import ObjectId
import re

from pymongo import MongoClient
from flask_pymongo import PyMongo #needed?
import argparse
import os
from web_interface.user_data import VonUser # work our why it doesn't like this import when it's in the same directory


#For details, see https://naoinstitute.atlassian.net/browse/JVNAUTOSCI-111
# write a minimal local web page server, that includes login and identity tracking, and
Expand Down Expand Up @@ -43,17 +51,63 @@ def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']

hpass=generate_password_hash(password, method='pbkdf2:sha256')

# Verify username and password
user = VonUser(username)
if user and user.get_password() == password: # In production, use hashed passwords
user = VonUser.find_by_username(username)
if user and check_password_hash(hpass,password): # In production, use hashed passwords
login_user(User(username))
return redirect(url_for('dashboard'))
else:
return 'Invalid credentials', 401
flash('Login Unsuccessful. Please try again or signup.', 'error')
return redirect(url_for('login'))
#return 'Invalid credentials', 401

return render_template('login.html')

@app.route('/signup', methods=['GET', 'POST'])
def signup():
if request.method == 'POST':
# Get form data
username = request.form['username']
email = request.form['email']
password = request.form['password']
confirm_password = request.form['confirm_password']

# Validate form data
if not username or not email or not password or not confirm_password:
flash('Please fill out all fields.', 'error')
return redirect(url_for('signup'))

if password != confirm_password:
flash('Passwords do not match.', 'error')
return redirect(url_for('signup'))

existing_user = VonUser.find_by_username(username)
# Check if user already exists
if existing_user and username == existing_user.get_username():
flash('Username already exists.', 'error')
return redirect(url_for('signup'))

#Validate email format
email_regex = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
if not re.match(email_regex, email):
flash('Invalid email format.', 'error')
return redirect(url_for('signup'))

hpass=generate_password_hash(password, method='pbkdf2:sha256')
newUser=VonUser.create_user(username, email, hpass) #create_user is a class method
if not newUser:
flash('Error creating user.', 'error')
return redirect(url_for('signup'))


flash('Registration successful. Please log in.', 'success')
return redirect(url_for('login'))

return render_template('signup.html')


@app.route('/dashboard')
@login_required
def dashboard():
Expand All @@ -76,6 +130,7 @@ def logout():
if args.background:
from multiprocessing import Process


def run_app():
app.run(host=args.host, port=args.port)

Expand Down
18 changes: 16 additions & 2 deletions src/web_interface/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,26 @@
</head>
<body>
<h1>Login</h1>
<!-- Display flash messages -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul>
{% for category, message in messages %}
<li style="color: {% if category == 'error' %}red{% else %}green{% endif %};">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<!-- Login form -->
<form action="{{ url_for('login') }}" method="post">
<label for="username">Username:</label>
<label for="username">Username:</label><br>
<input type="text" name="username" id="username" required autofocus><br><br>
<label for="password">Password:</label>

<label for="password">Password:</label><br>
<input type="password" name="password" id="password" required><br><br>

<button type="submit">Login</button>
</form>
<p>Don't have an account? <a href="{{ url_for('signup') }}">Sign up here</a>.</p>
</body>
</html>
37 changes: 37 additions & 0 deletions src/web_interface/templates/signup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Signup</title>
</head>
<body>
<h1>Sign Up</h1>
<!-- Display flash messages -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul>
{% for category, message in messages %}
<li style="color: {% if category == 'error' %}red{% else %}green{% endif %};">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<!-- Signup form -->
<form action="{{ url_for('signup') }}" method="post">
<label for="username">Username:</label><br>
<input type="text" name="username" id="username" required autofocus><br><br>

<label for="email">Email:</label><br>
<input type="text" name="email" id="email" required><br><br>

<label for="password">Password:</label><br>
<input type="password" name="password" id="password" required><br><br>

<label for="confirm_password">Confirm Password:</label><br>
<input type="password" name="confirm_password" id="confirm_password" required><br><br>

<button type="submit">Register</button>
</form>
<p>Already have an account? <a href="{{ url_for('login') }}">Log in here</a>.</p>
</body>
</html>
37 changes: 34 additions & 3 deletions src/web_interface/user_data.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from bson.objectid import ObjectId
from werkzeug.security import generate_password_hash, check_password_hash

from vonlib import database_driver as vondb

config = {}
Expand Down Expand Up @@ -42,13 +44,36 @@ def set_userDB(cls, userdb_name=vonuserdb, usercollection_name=vonusercollection
if user_collection is None:
raise Exception(f"Collection {usercollection_name} does not exist and could not be created.")

# put self in 湛 Zhan von Neumarkt <[email protected]>
user_collection.insert_one({'username': 'zhan', 'email': '[email protected]','password': 'password'})

cls.userdb = user_database
cls.usercollection = user_collection
print(f"VonUser: DB={cls.userdb.name}, Coll={cls.usercollection.name}")

@classmethod
def create_user(cls, username, email, password):
"""
Creates a new user in the user database collection.
This method creates a new user document in the user database collection. The user document
contains the provided username, email, and password.
Args:
username (str): The username of the new user.
email (str): The email of the new user.
password (str): The password of the new user.
Returns:
VonUser: A VonUser object representing the new user.
"""

user_dict = {
'username': username,
'email': email,
'password': password #should be hashed by now
}

cls.get_userCollection().insert_one(user_dict)
return VonUser(username)

@classmethod
def get_userCollection(cls):
return cls.usercollection
Expand All @@ -64,6 +89,12 @@ def find_by_id(cls, id):
return None
return VonUser(vu['username']) #return VonUser object

@classmethod
def find_by_username(cls, username):
vu=cls.get_userCollection().find_one({"username": username})
if vu is None:
return None
return VonUser(username) #return VonUser object


def __init__(self, username):
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/test_vonlib/llmconnect_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def test_ask_llm_1(self): #, mock_openai):
assert response is not None
expected_response = "os"
self.assertIn(expected_response, response)
expected_response = "listdir"
expected_response = "listdir" #this doesn't always happen
self.assertIn(expected_response, response)


Expand Down

0 comments on commit 7649bfb

Please sign in to comment.