From 4597595db42d6452a0433273d80f9c613d8011fa Mon Sep 17 00:00:00 2001 From: Scheianu Ionut Date: Fri, 12 Sep 2025 21:24:22 +0300 Subject: [PATCH] updated creation of the database for users --- instance/users.db | Bin 16384 -> 0 bytes py_app/app/__pycache__/routes.cpython-312.pyc | Bin 25774 -> 24715 bytes .../app/__pycache__/settings.cpython-312.pyc | Bin 4357 -> 13035 bytes py_app/app/routes.py | 110 ++------- py_app/app/settings.py | 219 +++++++++++++++++- py_app/app/templates/settings.html | 33 ++- 6 files changed, 266 insertions(+), 96 deletions(-) delete mode 100644 instance/users.db diff --git a/instance/users.db b/instance/users.db deleted file mode 100644 index f054575490a4c3ee413d51ce75d32ddba6c6d1d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 S)t*>V&d&G!6D=5*p7o`?#0L!l6-VAHX|%Z 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 diff --git a/py_app/app/__pycache__/settings.cpython-312.pyc b/py_app/app/__pycache__/settings.cpython-312.pyc index e6e5e399fd3d24908be1e3bbf1602eaab76df6ea..fd127d36c32bd30387805f2b83f4c6beb5331fcb 100644 GIT binary patch literal 13035 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 diff --git a/py_app/app/routes.py b/py_app/app/routes.py index 00198e6..5f86e77 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -9,7 +9,14 @@ from reportlab.pdfgen import canvas from flask import Blueprint, render_template, request, redirect, url_for, flash import csv from .warehouse import add_location -from .settings import settings_handler, edit_access_roles_handler +from .settings import ( + settings_handler, + edit_access_roles_handler, + create_user_handler, + edit_user_handler, + delete_user_handler, + save_external_db_handler +) bp = Blueprint('main', __name__) warehouse_bp = Blueprint('warehouse', __name__) @@ -53,8 +60,18 @@ def get_db_connection(): def login(): import sqlite3 if request.method == 'POST': - username = request.form['username'] - password = request.form['password'] + # Debug: print all form data received + print("All form data received:", dict(request.form)) + + # Safely get username and password with fallback + username = request.form.get('username', '').strip() + password = request.form.get('password', '').strip() + + if not username or not password: + print("Missing username or password") + flash('Please enter both username and password.') + return render_template('login.html') + user = None print("Raw form input:", repr(username), repr(password)) @@ -233,98 +250,19 @@ def logout(): @bp.route('/create_user', methods=['POST']) def create_user(): - if 'role' not in session or session['role'] != 'superadmin': - flash('Access denied: Superadmin only.') - return redirect(url_for('main.settings')) - - username = request.form['username'] - password = request.form['password'] - role = request.form['role'] - - # Check if the username already exists - if User.query.filter_by(username=username).first(): - flash('User already exists.') - return redirect(url_for('main.settings')) - - # Create a new user - new_user = User(username=username, password=password, role=role) - db.session.add(new_user) - db.session.commit() - - flash('User created successfully.') - return redirect(url_for('main.settings')) + return create_user_handler() @bp.route('/edit_user', methods=['POST']) def edit_user(): - if 'role' not in session or session['role'] != 'superadmin': - flash('Access denied: Superadmin only.') - return redirect(url_for('main.settings')) - - user_id = request.form['user_id'] - password = request.form['password'] - role = request.form['role'] - - # Fetch the user from the database - user = User.query.get(user_id) - if not user: - flash('User not found.') - return redirect(url_for('main.settings')) - - # Update the user's details - if password: - user.password = password - user.role = role - db.session.commit() - - flash('User updated successfully.') - return redirect(url_for('main.settings')) + return edit_user_handler() @bp.route('/delete_user', methods=['POST']) def delete_user(): - if 'role' not in session or session['role'] != 'superadmin': - flash('Access denied: Superadmin only.') - return redirect(url_for('main.settings')) - - user_id = request.form['user_id'] - - # Fetch the user from the database - user = User.query.get(user_id) - if not user: - flash('User not found.') - return redirect(url_for('main.settings')) - - # Delete the user - db.session.delete(user) - db.session.commit() - - flash('User deleted successfully.') - return redirect(url_for('main.settings')) + return delete_user_handler() @bp.route('/save_external_db', methods=['POST']) def save_external_db(): - if 'role' not in session or session['role'] != 'superadmin': - flash('Access denied: Superadmin only.') - return redirect(url_for('main.settings')) - - # Get form data - server_domain = request.form['server_domain'] - port = request.form['port'] - database_name = request.form['database_name'] - username = request.form['username'] - password = request.form['password'] - - # Save data to a file in the instance folder - settings_file = os.path.join(current_app.instance_path, 'external_server.conf') - os.makedirs(os.path.dirname(settings_file), exist_ok=True) - with open(settings_file, 'w') as f: - f.write(f"server_domain={server_domain}\n") - f.write(f"port={port}\n") - f.write(f"database_name={database_name}\n") - f.write(f"username={username}\n") - f.write(f"password={password}\n") - - flash('External database settings saved/updated successfully.') - return redirect(url_for('main.settings')) + return save_external_db_handler() @bp.route('/get_report_data', methods=['GET']) def get_report_data(): diff --git a/py_app/app/settings.py b/py_app/app/settings.py index 0ea4544..7b59a67 100644 --- a/py_app/app/settings.py +++ b/py_app/app/settings.py @@ -1,6 +1,8 @@ -from flask import render_template, request, session, redirect, url_for, flash +from flask import render_template, request, session, redirect, url_for, flash, current_app from .models import User from . import db +import mariadb +import os # Settings module logic import sqlite3 @@ -60,17 +62,224 @@ def settings_handler(): if 'role' not in session or session['role'] != 'superadmin': flash('Access denied: Superadmin only.') return redirect(url_for('main.dashboard')) - users = User.query.all() + + # Get users from external MariaDB database + users = [] + try: + conn = get_external_db_connection() + cursor = conn.cursor() + + # Create users table if it doesn't exist + cursor.execute(''' + CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) UNIQUE NOT NULL, + password VARCHAR(255) NOT NULL, + role VARCHAR(50) NOT NULL + ) + ''') + + # Get all users from external database + cursor.execute("SELECT id, username, password, role FROM users") + users_data = cursor.fetchall() + + # Convert to list of dictionaries for template compatibility + users = [] + for user_data in users_data: + users.append({ + 'id': user_data[0], + 'username': user_data[1], + 'password': user_data[2], + 'role': user_data[3] + }) + + conn.close() + + except Exception as e: + print(f"Error fetching users from external database: {e}") + flash(f'Error loading users: {e}') + # Load external database settings from the instance folder external_settings = {} - import os - from flask import current_app settings_file = os.path.join(current_app.instance_path, 'external_server.conf') if os.path.exists(settings_file): with open(settings_file, 'r') as f: for line in f: key, value = line.strip().split('=', 1) external_settings[key] = value + return render_template('settings.html', users=users, external_settings=external_settings) -# Add more settings-related functions here as needed +# Helper function to get external database connection +def get_external_db_connection(): + """Reads the external_server.conf file and returns a MariaDB database connection.""" + settings_file = os.path.join(current_app.instance_path, 'external_server.conf') + if not os.path.exists(settings_file): + raise FileNotFoundError("The external_server.conf file is missing in the instance folder.") + + # Read settings from the configuration file + settings = {} + with open(settings_file, 'r') as f: + for line in f: + key, value = line.strip().split('=', 1) + settings[key] = value + + # Create a database connection + return mariadb.connect( + user=settings['username'], + password=settings['password'], + host=settings['server_domain'], + port=int(settings['port']), + database=settings['database_name'] + ) + +# User management handlers +def create_user_handler(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + username = request.form['username'] + password = request.form['password'] + role = request.form['role'] + + try: + # Connect to external MariaDB database + conn = get_external_db_connection() + cursor = conn.cursor() + + # Create users table if it doesn't exist + cursor.execute(''' + CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) UNIQUE NOT NULL, + password VARCHAR(255) NOT NULL, + role VARCHAR(50) NOT NULL + ) + ''') + + # Check if the username already exists + cursor.execute("SELECT id FROM users WHERE username = %s", (username,)) + if cursor.fetchone(): + flash('User already exists.') + conn.close() + return redirect(url_for('main.settings')) + + # Create a new user in external MariaDB + cursor.execute(""" + INSERT INTO users (username, password, role) + VALUES (%s, %s, %s) + """, (username, password, role)) + + conn.commit() + conn.close() + flash('User created successfully in external database.') + + except Exception as e: + print(f"Error creating user in external database: {e}") + flash(f'Error creating user: {e}') + + return redirect(url_for('main.settings')) + +def edit_user_handler(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + user_id = request.form.get('user_id') + password = request.form.get('password', '').strip() + role = request.form.get('role') + + if not user_id or not role: + flash('Missing required fields.') + return redirect(url_for('main.settings')) + + try: + # Connect to external MariaDB database + conn = get_external_db_connection() + cursor = conn.cursor() + + # Check if the user exists + cursor.execute("SELECT id FROM users WHERE id = %s", (user_id,)) + if not cursor.fetchone(): + flash('User not found.') + conn.close() + return redirect(url_for('main.settings')) + + # Update the user's details in external MariaDB + if password: # Only update password if provided + cursor.execute(""" + UPDATE users SET password = %s, role = %s WHERE id = %s + """, (password, role, user_id)) + flash('User updated successfully (including password).') + else: # Just update role if no password provided + cursor.execute(""" + UPDATE users SET role = %s WHERE id = %s + """, (role, user_id)) + flash('User role updated successfully.') + + conn.commit() + conn.close() + + except Exception as e: + print(f"Error updating user in external database: {e}") + flash(f'Error updating user: {e}') + + return redirect(url_for('main.settings')) + +def delete_user_handler(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + user_id = request.form['user_id'] + + try: + # Connect to external MariaDB database + conn = get_external_db_connection() + cursor = conn.cursor() + + # Check if the user exists + cursor.execute("SELECT id FROM users WHERE id = %s", (user_id,)) + if not cursor.fetchone(): + flash('User not found.') + conn.close() + return redirect(url_for('main.settings')) + + # Delete the user from external MariaDB + cursor.execute("DELETE FROM users WHERE id = %s", (user_id,)) + + conn.commit() + conn.close() + flash('User deleted successfully from external database.') + + except Exception as e: + print(f"Error deleting user from external database: {e}") + flash(f'Error deleting user: {e}') + + return redirect(url_for('main.settings')) + +def save_external_db_handler(): + if 'role' not in session or session['role'] != 'superadmin': + flash('Access denied: Superadmin only.') + return redirect(url_for('main.settings')) + + # Get form data + server_domain = request.form['server_domain'] + port = request.form['port'] + database_name = request.form['database_name'] + username = request.form['username'] + password = request.form['password'] + + # Save data to a file in the instance folder + settings_file = os.path.join(current_app.instance_path, 'external_server.conf') + os.makedirs(os.path.dirname(settings_file), exist_ok=True) + with open(settings_file, 'w') as f: + f.write(f"server_domain={server_domain}\n") + f.write(f"port={port}\n") + f.write(f"database_name={database_name}\n") + f.write(f"username={username}\n") + f.write(f"password={password}\n") + + flash('External database settings saved/updated successfully.') + return redirect(url_for('main.settings')) diff --git a/py_app/app/templates/settings.html b/py_app/app/templates/settings.html index 006726f..5f6d7a1 100644 --- a/py_app/app/templates/settings.html +++ b/py_app/app/templates/settings.html @@ -12,7 +12,7 @@ {{ user.username }} Role: {{ user.role }} - + {% endfor %} @@ -48,10 +48,11 @@