Added user login functionality

This commit is contained in:
Candifloss 2025-03-08 11:53:34 +05:30
parent ff4336f655
commit 12b902c382
13 changed files with 100 additions and 1 deletions

View File

@ -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

4
app.py
View File

@ -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)

10
functions/auth.py Normal file
View File

@ -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

View File

@ -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')

View File

@ -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

View File

@ -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/<path:primary_value>/', methods=['GET', 'POST'])
@login_required
def delete(primary_value):
# Identify the primary attribute
primary_attrib = next(

View File

@ -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()

41
routes/homepage.py Normal file
View File

@ -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'))

View File

@ -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/<string:primary_value>/', 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)

View File

@ -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':

View File

@ -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()

26
templates/login.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Page</title>
</head>
<body>
<div class="left-container">
<img src="../images/logo2.png" alt="Company Logo" class="logo">
<h1>Inventory Manager</h1>
<p>Inventory management system</p>
</div>
<div class="login-container">
<h2>Login</h2>
<form action="/login" method="post">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
</div>
</body>
</html>

View File

@ -49,5 +49,8 @@
<form action="/export_csv" method="POST">
<button type="submit">Export Data</button>
</form>
<form action="/logout" method="get">
<button type="submit">Logout</button>
</form>
</body>
</html>