From 06769db06c3121ae0f8d74847473e4687d68d38b Mon Sep 17 00:00:00 2001 From: iltenahmet Date: Tue, 27 Feb 2024 09:21:02 -0500 Subject: [PATCH 1/4] Show messages if username is taken or confirm password don't match --- app.py | 4 ++-- authentication.py | 40 +++++++++++++++++++++++++++------------- static/css/style.css | 6 +++++- templates/signup.html | 8 +++++++- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/app.py b/app.py index fb7f021..945ebfa 100644 --- a/app.py +++ b/app.py @@ -18,11 +18,11 @@ def home(): # Handle authentication related stuff in authentication.py file @app.route('/login', methods=["GET", "POST"]) def login(): - return authLogin() + return auth_login() @app.route('/signup', methods=["GET", "POST"]) def signup(): - return authSignup() + return auth_signup() @app.route("//decks") def allDecks(username): diff --git a/authentication.py b/authentication.py index e76ec9a..e72d527 100644 --- a/authentication.py +++ b/authentication.py @@ -1,31 +1,45 @@ from flask import render_template, request, redirect, url_for, session -from flask_login import LoginManager +from flask_login import LoginManager, UserMixin from db import * - +from pymongo import * +from werkzeug.security import generate_password_hash, check_password_hash login_manager = LoginManager() -class User(): - def __init__(self, username, password, is_authenticated, is_active, is_anonymous): - self.is_authenticated = is_authenticated - self.is_active = is_active - self.is_anonymous = is_anonymous - @login_manager.user_loader -def load_user(user_id): - return User.get(user_id) +def load_user(username): + return db['users'].find_one({"username": username}) + +class User(UserMixin): + def __init__(self, username, password): + self.username = username + self.password = generate_password_hash(password) -def authLogin(): + def verify_password(self, pwd): + return check_password_hash(self.password, pwd) + +def auth_login(): + collections = db.list_collection_names() if request.method == 'POST': + for collection in collections: + print("Collection name: " + collection) + ## TODO: Login return "Someone pressed the login button huh, I better log you in." else: return render_template('login.html') -def authSignup(): +def auth_signup(): if request.method == 'POST': username = request.form["username"] password = request.form["password"] + confirm_password = request.form["confirm-password"] + if (load_user(username)): + return render_template('signup.html', username_taken=True, passwords_dont_match=False) + elif(password != confirm_password): + return render_template('signup.html', username_taken=False, passwords_dont_match=True) + else: + return "Username doesn't exist, we should probably sign you up." else: - return render_template('signup.html') + return render_template('signup.html', username_taken=False, passwords_dont_match=False) diff --git a/static/css/style.css b/static/css/style.css index 66b2a36..3797b86 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -126,4 +126,8 @@ h3 { display: flex; justify-content: center; align-items: center; -} \ No newline at end of file +} + +.signup-error { + font-size: 25px; +} diff --git a/templates/signup.html b/templates/signup.html index 03c05d4..d659d7b 100644 --- a/templates/signup.html +++ b/templates/signup.html @@ -5,8 +5,14 @@
+ {% if username_taken %} + + {% endif %} - + + {% if passwords_dont_match %} + + {% endif %}
From 73d424d8ef23b2f29582f2980c63d0ecbba8562d Mon Sep 17 00:00:00 2001 From: iltenahmet Date: Tue, 27 Feb 2024 09:21:02 -0500 Subject: [PATCH 2/4] Show messages if username is taken or confirm password don't match --- app.py | 4 ++-- authentication.py | 40 +++++++++++++++++++++++++++------------- static/css/style.css | 4 ++++ templates/signup.html | 8 +++++++- 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/app.py b/app.py index 5a25882..2d66e13 100644 --- a/app.py +++ b/app.py @@ -19,11 +19,11 @@ def home(): # Handle authentication related stuff in authentication.py file @app.route('/login', methods=["GET", "POST"]) def login(): - return authLogin() + return auth_login() @app.route('/signup', methods=["GET", "POST"]) def signup(): - return authSignup() + return auth_signup() @app.route("//decks") def allDecks(username): diff --git a/authentication.py b/authentication.py index e76ec9a..e72d527 100644 --- a/authentication.py +++ b/authentication.py @@ -1,31 +1,45 @@ from flask import render_template, request, redirect, url_for, session -from flask_login import LoginManager +from flask_login import LoginManager, UserMixin from db import * - +from pymongo import * +from werkzeug.security import generate_password_hash, check_password_hash login_manager = LoginManager() -class User(): - def __init__(self, username, password, is_authenticated, is_active, is_anonymous): - self.is_authenticated = is_authenticated - self.is_active = is_active - self.is_anonymous = is_anonymous - @login_manager.user_loader -def load_user(user_id): - return User.get(user_id) +def load_user(username): + return db['users'].find_one({"username": username}) + +class User(UserMixin): + def __init__(self, username, password): + self.username = username + self.password = generate_password_hash(password) -def authLogin(): + def verify_password(self, pwd): + return check_password_hash(self.password, pwd) + +def auth_login(): + collections = db.list_collection_names() if request.method == 'POST': + for collection in collections: + print("Collection name: " + collection) + ## TODO: Login return "Someone pressed the login button huh, I better log you in." else: return render_template('login.html') -def authSignup(): +def auth_signup(): if request.method == 'POST': username = request.form["username"] password = request.form["password"] + confirm_password = request.form["confirm-password"] + if (load_user(username)): + return render_template('signup.html', username_taken=True, passwords_dont_match=False) + elif(password != confirm_password): + return render_template('signup.html', username_taken=False, passwords_dont_match=True) + else: + return "Username doesn't exist, we should probably sign you up." else: - return render_template('signup.html') + return render_template('signup.html', username_taken=False, passwords_dont_match=False) diff --git a/static/css/style.css b/static/css/style.css index 5a5d1e3..9ac147c 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -116,3 +116,7 @@ h3 { justify-content: center; align-items: center; } + +.signup-error { + font-size: 25px; +} diff --git a/templates/signup.html b/templates/signup.html index 03c05d4..d659d7b 100644 --- a/templates/signup.html +++ b/templates/signup.html @@ -5,8 +5,14 @@
+ {% if username_taken %} + + {% endif %} - + + {% if passwords_dont_match %} + + {% endif %}
From e35f703210e5c89d3473a635d0d27d5c3799ca1a Mon Sep 17 00:00:00 2001 From: iltenahmet Date: Tue, 27 Feb 2024 10:46:14 -0500 Subject: [PATCH 3/4] Finish signing the user up --- app.py | 7 +++++++ authentication.py | 49 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/app.py b/app.py index 2d66e13..cb364a3 100644 --- a/app.py +++ b/app.py @@ -4,6 +4,12 @@ import random app = Flask(__name__) +login_manager.init_app(app) + +# Secret key for login session management, set this up in your .env file +load_dotenv() +app.secret_key = os.getenv("SECRET_KEY") + @app.route("/", methods=["GET", "POST"]) def home(): @@ -103,3 +109,4 @@ def deleteDeck(username, deckTitle): if __name__ == "__main__": FLASK_PORT = os.getenv("FLASK_PORT", "5000") app.run(port=FLASK_PORT) + diff --git a/authentication.py b/authentication.py index e72d527..97cd583 100644 --- a/authentication.py +++ b/authentication.py @@ -1,5 +1,5 @@ -from flask import render_template, request, redirect, url_for, session -from flask_login import LoginManager, UserMixin +from flask import render_template, request, redirect, url_for, session, flash +from flask_login import LoginManager, UserMixin, login_user from db import * from pymongo import * from werkzeug.security import generate_password_hash, check_password_hash @@ -7,39 +7,58 @@ login_manager = LoginManager() @login_manager.user_loader -def load_user(username): - return db['users'].find_one({"username": username}) +def load_user(user_id): + data = db['users'].find_one({"user_id": user_id}) + if (data): + return User(data['user_id'], data['password']) + else: + return None class User(UserMixin): - def __init__(self, username, password): - self.username = username - self.password = generate_password_hash(password) + def __init__(self, user_id, password): + self.id = user_id + self.password = password def verify_password(self, pwd): return check_password_hash(self.password, pwd) +''' +NOTE: +To get the active user from anywhere else or a different file +you need to import flask_login first then you can retrieve the active user with current_user +Example: + from flask_login import current_user + user = current_user +''' + def auth_login(): collections = db.list_collection_names() if request.method == 'POST': - for collection in collections: - print("Collection name: " + collection) - - ## TODO: Login - return "Someone pressed the login button huh, I better log you in." + # TODO: Log the user in + # TODO: Redirect to the appropriate page for the logged in user + return redirect('/') else: return render_template('login.html') + def auth_signup(): if request.method == 'POST': - username = request.form["username"] + user_id = request.form["username"] password = request.form["password"] confirm_password = request.form["confirm-password"] - if (load_user(username)): + if (load_user(user_id)): return render_template('signup.html', username_taken=True, passwords_dont_match=False) elif(password != confirm_password): return render_template('signup.html', username_taken=False, passwords_dont_match=True) else: - return "Username doesn't exist, we should probably sign you up." + user = User(user_id, generate_password_hash(password)) + db['users'].insert_one({"user_id": user.id, "password": user.password}) + login_user(user) + # TODO: Redirect to the appropriate page for the logged in user + return redirect('/') + else: return render_template('signup.html', username_taken=False, passwords_dont_match=False) + + From d5331f5e622a08100dbf5474f88398d418411751 Mon Sep 17 00:00:00 2001 From: iltenahmet Date: Tue, 27 Feb 2024 14:14:37 -0500 Subject: [PATCH 4/4] Implement logging in --- app.py | 11 ++++++--- authentication.py | 55 ++++++++++++++++++++++++++------------------ static/css/style.css | 2 +- templates/login.html | 3 +++ 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/app.py b/app.py index cb364a3..86413cc 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,5 @@ from flask import Flask, render_template, request, redirect, abort, url_for, make_response +from flask_login import current_user from authentication import * from db import * import random @@ -10,7 +11,6 @@ load_dotenv() app.secret_key = os.getenv("SECRET_KEY") - @app.route("/", methods=["GET", "POST"]) def home(): if request.method == 'POST': @@ -33,12 +33,17 @@ def signup(): @app.route("//decks") def allDecks(username): - # would need to first find user in db, but not set up yet if username == "guest": mainDecks = db.decks.find({}) return render_template('decks.html', mainDecks=mainDecks) else: - return "to do: for users" + if (not current_user.is_authenticated or current_user.id != username): + # TODO: Implement proper 404 screen to redirect here. + return username + " needs to log in first." + else: + # TODO: Redirect to the decks of the current user + return "Here would be the decks of " + current_user.id + "." + @app.route("//") def displayDeck(username, deckTitle): diff --git a/authentication.py b/authentication.py index 97cd583..1f6a91f 100644 --- a/authentication.py +++ b/authentication.py @@ -6,14 +6,18 @@ login_manager = LoginManager() -@login_manager.user_loader -def load_user(user_id): - data = db['users'].find_one({"user_id": user_id}) - if (data): - return User(data['user_id'], data['password']) - else: - return None - +''' +NOTE: +To get the active user from a different file or somewhere else +you need to import flask_login first then you can retrieve the active user with current_user +Example: + from flask_login import current_user + if current_user.is_authenticated: + # Do something with current_user +Also check allDecks function in app.py for example usage +''' +# Automatically implements is_authenticated, is_anonymous, is_active and get_id() +# through UserMixin class User(UserMixin): def __init__(self, user_id, password): self.id = user_id @@ -22,23 +26,30 @@ def __init__(self, user_id, password): def verify_password(self, pwd): return check_password_hash(self.password, pwd) -''' -NOTE: -To get the active user from anywhere else or a different file -you need to import flask_login first then you can retrieve the active user with current_user -Example: - from flask_login import current_user - user = current_user -''' + +@login_manager.user_loader +def load_user(user_id): + data = db['users'].find_one({"user_id": user_id}) + if (data): + return User(data['user_id'], data['password']) + else: + return None + def auth_login(): collections = db.list_collection_names() if request.method == 'POST': - # TODO: Log the user in - # TODO: Redirect to the appropriate page for the logged in user - return redirect('/') + user_id = request.form["username"] + password = request.form["password"] + user = load_user(user_id) + if user and user.verify_password(password): + # TODO: Redirect to the appropriate page for the logged in user + login_user(user) + return redirect('/') + else: + return render_template('login.html', invalid_login=True) else: - return render_template('login.html') + return render_template('login.html', invalid_login=False) def auth_signup(): @@ -46,9 +57,9 @@ def auth_signup(): user_id = request.form["username"] password = request.form["password"] confirm_password = request.form["confirm-password"] - if (load_user(user_id)): + if load_user(user_id): return render_template('signup.html', username_taken=True, passwords_dont_match=False) - elif(password != confirm_password): + elif password != confirm_password: return render_template('signup.html', username_taken=False, passwords_dont_match=True) else: user = User(user_id, generate_password_hash(password)) diff --git a/static/css/style.css b/static/css/style.css index 9ac147c..76cca7e 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -117,6 +117,6 @@ h3 { align-items: center; } -.signup-error { +.signup-error, .login-error { font-size: 25px; } diff --git a/templates/login.html b/templates/login.html index 06b9613..0bc1657 100644 --- a/templates/login.html +++ b/templates/login.html @@ -6,6 +6,9 @@
+ {% if invalid_login %} + + {% endif %}