From 12b902c3828aa8600cf4d4c82ffa69f6c7c09366 Mon Sep 17 00:00:00 2001 From: candifloss Date: Sat, 8 Mar 2025 11:53:34 +0530 Subject: [PATCH] Added user login functionality --- README.md | 2 +- app.py | 4 ++++ functions/auth.py | 10 ++++++++++ routes/confirm_save.py | 2 ++ routes/create.py | 2 ++ routes/delete.py | 2 ++ routes/export_csv.py | 2 ++ routes/homepage.py | 41 +++++++++++++++++++++++++++++++++++++++++ routes/update.py | 2 ++ routes/upload.py | 3 +++ routes/viewall.py | 2 ++ templates/login.html | 26 ++++++++++++++++++++++++++ templates/viewList.html | 3 +++ 13 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 functions/auth.py create mode 100644 routes/homepage.py create mode 100644 templates/login.html diff --git a/README.md b/README.md index d86c49c..da1a017 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A minimal python flask app for inventory management, with some basic functionality: - Fetch and display items from the MySQL db as an html table - Add new items to the db (individually) using a form -- Edit existing (individual)items in the db using a for +- Edit existing (individual) items in the db using a form - Delete (individual)items in the db - Add a batch of new items from a csv file - Edit a batch of existing items with new data from a csv file diff --git a/app.py b/app.py index 9c60370..de5b752 100644 --- a/app.py +++ b/app.py @@ -12,6 +12,7 @@ from sqlalchemy import exc from definitions.models import * # Import the Blueprints +from routes.homepage import homepage_bp from routes.viewall import viewall_bp from routes.export_csv import export_csv_bp from routes.create import addasset_bp @@ -27,6 +28,7 @@ app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) # Register the Blueprints +app.register_blueprint(homepage_bp) app.register_blueprint(viewall_bp) app.register_blueprint(export_csv_bp) app.register_blueprint(addasset_bp) @@ -44,9 +46,11 @@ with app.app_context(): print(f"Database Error: Failed to create tables. {str(e)}") raise SystemExit("Database connection failed. Please check your configuration.") +""" @app.route('/') def index(): return redirect('/viewall') +""" if __name__ == '__main__': app.run(host='localhost', port=5000) diff --git a/functions/auth.py b/functions/auth.py new file mode 100644 index 0000000..9c63484 --- /dev/null +++ b/functions/auth.py @@ -0,0 +1,10 @@ +from functools import wraps # Import wraps +from flask import session, redirect, url_for + +def login_required(f): + @wraps(f) # Preserve the original function's metadata + def decorated_function(*args, **kwargs): + if 'username' not in session: + return redirect(url_for('homepage.login')) + return f(*args, **kwargs) + return decorated_function \ No newline at end of file diff --git a/routes/confirm_save.py b/routes/confirm_save.py index b6c139e..7b157ea 100644 --- a/routes/confirm_save.py +++ b/routes/confirm_save.py @@ -3,10 +3,12 @@ from definitions.models import Asset, db from functions.validate_values import validate_values from config import item_attributes import json +from functions.auth import login_required confirm_save_bp = Blueprint('confirm_save', __name__) @confirm_save_bp.route('/confirm_save', methods=['POST']) +@login_required def confirm_save(): # Retrieve mode from session mode = session.get('csv_mode') diff --git a/routes/create.py b/routes/create.py index e4abc7c..e939956 100644 --- a/routes/create.py +++ b/routes/create.py @@ -3,10 +3,12 @@ from definitions.models import Asset, db from config import item_attributes from sqlalchemy import exc # Import exc for database exceptions from functions.validate_values import validate_values # Form validation +from functions.auth import login_required addasset_bp = Blueprint('addasset', __name__) @addasset_bp.route('/create/', methods=['GET', 'POST']) +@login_required def create(): if request.method == 'GET': # Render the "add item" form diff --git a/routes/delete.py b/routes/delete.py index bb49718..374d022 100644 --- a/routes/delete.py +++ b/routes/delete.py @@ -1,10 +1,12 @@ from flask import Blueprint, request, render_template, redirect, flash from definitions.models import Asset, db from config import item_attributes +from functions.auth import login_required delete_bp = Blueprint('deleteasset', __name__) @delete_bp.route('/delete//', methods=['GET', 'POST']) +@login_required def delete(primary_value): # Identify the primary attribute primary_attrib = next( diff --git a/routes/export_csv.py b/routes/export_csv.py index 5a57b6c..cd37cd3 100644 --- a/routes/export_csv.py +++ b/routes/export_csv.py @@ -3,10 +3,12 @@ from definitions.models import Asset from config import item_attributes import csv import io +from functions.auth import login_required export_csv_bp = Blueprint('export_csv', __name__) @export_csv_bp.route('/export_csv', methods=['POST']) +@login_required def export_csv(): # Create an in-memory file-like object output = io.StringIO() diff --git a/routes/homepage.py b/routes/homepage.py new file mode 100644 index 0000000..929f373 --- /dev/null +++ b/routes/homepage.py @@ -0,0 +1,41 @@ +# routes/homepage.py +from flask import Blueprint, render_template, redirect, url_for, session, request, flash + +homepage_bp = Blueprint('homepage', __name__) + +# Hardcoded credentials for testing (replace with proper authentication in production) +VALID_USERNAME = "admin" +VALID_PASSWORD = "password" + +@homepage_bp.route('/') +def index(): + # Redirect to /viewall if the user is already logged in + if 'username' in session: + return redirect(url_for('viewall.view_list')) + # Otherwise, redirect to the login page + return redirect(url_for('homepage.login')) + +@homepage_bp.route('/login', methods=['GET', 'POST']) +def login(): + # Redirect to /viewall if the user is already logged in + if 'username' in session: + return redirect(url_for('viewall.view_list')) + + if request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + + # Validate credentials (replace with proper authentication logic) + if username == VALID_USERNAME and password == VALID_PASSWORD: + session['username'] = username # Store username in session + return redirect(url_for('viewall.view_list')) + else: + flash('Invalid username or password', 'error') + + return render_template('login.html') + +@homepage_bp.route('/logout') +def logout(): + # Remove the username from the session + session.pop('username', None) + return redirect(url_for('homepage.login')) \ No newline at end of file diff --git a/routes/update.py b/routes/update.py index bc06ee1..b41b3e6 100644 --- a/routes/update.py +++ b/routes/update.py @@ -3,10 +3,12 @@ from definitions.models import Asset, db from config import item_attributes from sqlalchemy import exc # Import exc for database exceptions from functions.validate_values import validate_values # Form validation +from functions.auth import login_required update_bp = Blueprint('editasset', __name__) @update_bp.route('/update//', methods=['GET', 'POST']) +@login_required def update(primary_value): # Identify the primary attribute primary_attrib = next((attrib for attrib in item_attributes if attrib.primary), None) diff --git a/routes/upload.py b/routes/upload.py index 0c94132..1cbbe5b 100644 --- a/routes/upload.py +++ b/routes/upload.py @@ -3,6 +3,7 @@ from definitions.models import Asset, db from functions.process_csv import get_csv_data from functions.validate_values import validate_values from config import item_attributes +from functions.auth import login_required upload_bp = Blueprint('uploadcsv', __name__) @@ -55,6 +56,7 @@ def _process_csv_file(file, mode): }, None @upload_bp.route('/import_from_csv', methods=['GET', 'POST']) +@login_required def import_from_csv(): session['csv_mode'] = 'import' # Store mode in session if request.method == 'POST': @@ -94,6 +96,7 @@ def import_from_csv(): return render_template('upload.html', mode="import") @upload_bp.route('/edit_using_csv', methods=['GET', 'POST']) +@login_required def edit_using_csv(): session['csv_mode'] = 'edit' # Store mode in session if request.method == 'POST': diff --git a/routes/viewall.py b/routes/viewall.py index 26abaf3..9f97a39 100644 --- a/routes/viewall.py +++ b/routes/viewall.py @@ -1,10 +1,12 @@ from flask import Blueprint, render_template from definitions.models import Asset from config import item_attributes +from functions.auth import login_required viewall_bp = Blueprint('viewall', __name__) @viewall_bp.route('/viewall/', methods=['GET']) +@login_required def view_list(): # Fetch all items from the database items = Asset.query.all() diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..6d322de --- /dev/null +++ b/templates/login.html @@ -0,0 +1,26 @@ + + + + + + Login Page + + + +
+ +

Inventory Manager

+

Inventory management system

+
+ + + + + diff --git a/templates/viewList.html b/templates/viewList.html index fef8e1b..1c9aaba 100644 --- a/templates/viewList.html +++ b/templates/viewList.html @@ -49,5 +49,8 @@
+
+ +
\ No newline at end of file