""" User Management Blueprint Handles user CRUD operations """ from flask import Blueprint, render_template, request, jsonify, send_file, session from werkzeug.security import generate_password_hash, check_password_hash from blueprints.auth import login_required, can_user, get_current_user from io import BytesIO import json import os users_bp = Blueprint('users', __name__, url_prefix='/users') # Path to users file USERS_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data', 'users.json') def load_users(): """Load users from JSON file""" if os.path.exists(USERS_FILE): try: with open(USERS_FILE, 'r') as f: return json.load(f) except: return [] return [] def save_users(users): """Save users to JSON file""" os.makedirs(os.path.dirname(USERS_FILE), exist_ok=True) with open(USERS_FILE, 'w') as f: json.dump(users, f, indent=2) def permission_required(permission): """Decorator to require specific permission""" from functools import wraps def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if not can_user(permission): return jsonify({ 'status': 'error', 'message': 'Permission denied' }), 403 return f(*args, **kwargs) return decorated_function return decorator # Routes @users_bp.route('/') @login_required def user_manager(): """Serve the user management page""" if not can_user('manage_users'): return "
You don't have permission to manage users.
", 403 current_user_id = session.get('user_id', -1) return render_template('user_manager.html', current_user_id=current_user_id) @users_bp.route('/api', methods=['GET']) @login_required @permission_required('manage_users') def get_users(): """Get all users""" users = load_users() return jsonify({ 'status': 'success', 'users': users }) @users_bp.route('/api', methods=['POST']) @login_required @permission_required('manage_users') def add_user(): """Add a new user with hashed password""" try: data = request.json # Validate required fields if not data.get('username') or not data.get('password') or not data.get('defaultLocation'): return jsonify({ 'status': 'error', 'message': 'Username, password, and default location are required' }), 400 users = load_users() # Check if username already exists if any(user['username'] == data['username'] for user in users): return jsonify({ 'status': 'error', 'message': 'Username already exists' }), 400 # Hash the password hashed_password = generate_password_hash(data['password'], method='pbkdf2:sha256') # Get location settings location_settings = data.get('locationSettings', {}) default_location = data['defaultLocation'] # Ensure default location is accessible if default_location not in location_settings: location_settings[default_location] = {} location_settings[default_location]['accessible'] = True # Create new user new_user = { 'username': data['username'], 'password': hashed_password, 'defaultLocation': default_location, 'locationSettings': location_settings, 'permissions': data.get('permissions', {}), 'active': data.get('active', True) } users.append(new_user) save_users(users) return jsonify({ 'status': 'success', 'message': 'User added successfully', 'users': users }) except Exception as e: return jsonify({ 'status': 'error', 'message': str(e) }), 500 @users_bp.route('/api/