from flask import Blueprint, render_template, request, jsonify, session from werkzeug.security import generate_password_hash from db import query_db, execute_db from utils import role_required users_bp = Blueprint('users', __name__) @users_bp.route('/settings/users') @role_required('owner', 'admin') def manage_users(): """User management page""" # Get all users if session['role'] == 'owner': # Owners can see everyone users = query_db('SELECT * FROM Users ORDER BY role, full_name') else: # Admins can only see staff users = query_db("SELECT * FROM Users WHERE role = 'staff' ORDER BY full_name") return render_template('manage_users.html', users=users) @users_bp.route('/settings/users/add', methods=['POST']) @role_required('owner', 'admin') def add_user(): """Add a new user""" data = request.get_json() username = data.get('username', '').strip() password = data.get('password', '') first_name = data.get('first_name', '').strip() last_name = data.get('last_name', '').strip() email = data.get('email', '').strip() role = data.get('role', 'staff') branch = data.get('branch', 'Main') # Validation if not username or not password or not first_name or not last_name: return jsonify({'success': False, 'message': 'Username, password, first name, and last name are required'}) # Admins can't create admins or owners if session['role'] == 'admin' and role in ['admin', 'owner']: return jsonify({'success': False, 'message': 'Permission denied: Admins can only create Staff users'}) # Check if username exists existing = query_db('SELECT user_id FROM Users WHERE username = ?', [username], one=True) if existing: return jsonify({'success': False, 'message': 'Username already exists'}) # Create user full_name = f"{first_name} {last_name}" hashed_password = generate_password_hash(password) try: execute_db(''' INSERT INTO Users (username, password, full_name, role, branch, is_active) VALUES (?, ?, ?, ?, ?, 1) ''', [username, hashed_password, full_name, role, branch]) return jsonify({'success': True, 'message': 'User created successfully'}) except Exception as e: return jsonify({'success': False, 'message': f'Error creating user: {str(e)}'}) @users_bp.route('/settings/users/', methods=['GET']) @role_required('owner', 'admin') def get_user(user_id): """Get user details""" user = query_db('SELECT * FROM Users WHERE user_id = ?', [user_id], one=True) if not user: return jsonify({'success': False, 'message': 'User not found'}) # Admins can't view other admins or owners if session['role'] == 'admin' and user['role'] in ['admin', 'owner']: return jsonify({'success': False, 'message': 'Permission denied'}) # Split full name name_parts = user['full_name'].split(' ', 1) first_name = name_parts[0] if len(name_parts) > 0 else '' last_name = name_parts[1] if len(name_parts) > 1 else '' # Get email, handle None email = user['email'] if user['email'] else '' return jsonify({ 'success': True, 'user': { 'user_id': user['user_id'], 'username': user['username'], 'first_name': first_name, 'last_name': last_name, 'email': email, 'role': user['role'], 'branch': user['branch'], 'is_active': user['is_active'] } }) @users_bp.route('/settings/users//update', methods=['POST']) @role_required('owner', 'admin') def update_user(user_id): """Update user details""" data = request.get_json() # Get existing user user = query_db('SELECT * FROM Users WHERE user_id = ?', [user_id], one=True) if not user: return jsonify({'success': False, 'message': 'User not found'}) # Admins can't edit other admins or owners if session['role'] == 'admin' and user['role'] in ['admin', 'owner']: return jsonify({'success': False, 'message': 'Permission denied'}) # Can't edit yourself to change your own role or deactivate if user_id == session['user_id']: if data.get('role') != user['role']: return jsonify({'success': False, 'message': 'Cannot change your own role'}) if data.get('is_active') == 0: return jsonify({'success': False, 'message': 'Cannot deactivate yourself'}) # Build update username = data.get('username', '').strip() first_name = data.get('first_name', '').strip() last_name = data.get('last_name', '').strip() email = data.get('email', '').strip() role = data.get('role', user['role']) branch = data.get('branch', user['branch']) is_active = data.get('is_active', user['is_active']) password = data.get('password', '').strip() if not username or not first_name or not last_name: return jsonify({'success': False, 'message': 'Username, first name, and last name are required'}) # Check if username is taken by another user if username != user['username']: existing = query_db('SELECT user_id FROM Users WHERE username = ? AND user_id != ?', [username, user_id], one=True) if existing: return jsonify({'success': False, 'message': 'Username already taken'}) # Admins can't change role to admin or owner if session['role'] == 'admin' and role in ['admin', 'owner']: return jsonify({'success': False, 'message': 'Permission denied: Cannot assign Admin or Owner role'}) full_name = f"{first_name} {last_name}" try: if password: # Update with new password hashed_password = generate_password_hash(password) execute_db(''' UPDATE Users SET username = ?, full_name = ?, email = ?, role = ?, branch = ?, is_active = ?, password = ? WHERE user_id = ? ''', [username, full_name, email, role, branch, is_active, hashed_password, user_id]) else: # Update without changing password execute_db(''' UPDATE Users SET username = ?, full_name = ?, email = ?, role = ?, branch = ?, is_active = ? WHERE user_id = ? ''', [username, full_name, email, role, branch, is_active, user_id]) return jsonify({'success': True, 'message': 'User updated successfully'}) except Exception as e: return jsonify({'success': False, 'message': f'Error updating user: {str(e)}'}) @users_bp.route('/settings/users//delete', methods=['POST']) @role_required('owner', 'admin') def delete_user(user_id): """Delete (deactivate) a user""" # Get user user = query_db('SELECT * FROM Users WHERE user_id = ?', [user_id], one=True) if not user: return jsonify({'success': False, 'message': 'User not found'}) # Admins can't delete other admins or owners if session['role'] == 'admin' and user['role'] in ['admin', 'owner']: return jsonify({'success': False, 'message': 'Permission denied'}) # Can't delete yourself if user_id == session['user_id']: return jsonify({'success': False, 'message': 'Cannot delete yourself'}) # Soft delete (deactivate) try: execute_db('UPDATE Users SET is_active = 0 WHERE user_id = ?', [user_id]) return jsonify({'success': True, 'message': 'User deleted successfully'}) except Exception as e: return jsonify({'success': False, 'message': f'Error deleting user: {str(e)}'})