|
from flask import Blueprint, request, jsonify, session, current_app |
|
from app.models.user import User |
|
from app.utils.decorators import login_required, admin_required |
|
from bson.objectid import ObjectId |
|
|
|
user_bp = Blueprint('users', __name__) |
|
|
|
def get_mongo(): |
|
return current_app.extensions['pymongo'][0] |
|
|
|
def get_bcrypt(): |
|
return current_app.extensions['bcrypt'] |
|
|
|
@user_bp.route('/profile', methods=['GET']) |
|
def get_profile(): |
|
"""Get current user profile""" |
|
try: |
|
user_id = session['user_id'] |
|
user = User.find_by_id(user_id) |
|
|
|
if not user: |
|
return jsonify({"error": "User not found"}), 404 |
|
|
|
|
|
user_data = { |
|
"id": str(user['_id']), |
|
"email": user['email'], |
|
"first_name": user['first_name'], |
|
"last_name": user['last_name'], |
|
"role": user.get('role', 'customer'), |
|
"created_at": user.get('created_at'), |
|
"email_verified": user.get('email_verified', False), |
|
"last_login": user.get('last_login') |
|
} |
|
|
|
return jsonify({"user": user_data}), 200 |
|
|
|
except Exception as e: |
|
return jsonify({"error": "Failed to get profile", "details": str(e)}), 500 |
|
|
|
@user_bp.route('/profile', methods=['PUT']) |
|
def update_profile(): |
|
"""Update current user profile""" |
|
try: |
|
data = request.get_json() |
|
|
|
|
|
required_fields = ['id'] |
|
for field in required_fields: |
|
if field not in data or not data[field]: |
|
return jsonify({"error": f"{field} is required"}), 400 |
|
|
|
allowed_fields = ['name', 'email','phone', 'address'] |
|
update_data = {} |
|
|
|
for field in allowed_fields: |
|
if field in data and data[field]: |
|
update_data[field] = data[field] |
|
|
|
id = data['id'] |
|
|
|
|
|
success = User.update_user(id, update_data) |
|
if not success: |
|
return jsonify({"error": "Failed to update profile"}), 500 |
|
|
|
|
|
user = User.find_by_id(id) |
|
user_data = { |
|
"id": user['_id'], |
|
"email": user['email'], |
|
"name": user['name'], |
|
"phone": user['phone'], |
|
"address": user['address'] |
|
} |
|
|
|
return jsonify({ |
|
"message": "Profile updated successfully", |
|
"user": user_data |
|
}), 200 |
|
|
|
except Exception as e: |
|
return jsonify({"error": "Failed to update profile", "details": str(e)}), 500 |
|
|
|
@user_bp.route('/change-password', methods=['PUT']) |
|
@login_required |
|
def change_password(): |
|
"""Change user password""" |
|
try: |
|
user_id = session['user_id'] |
|
data = request.get_json() |
|
|
|
|
|
if not data.get('current_password') or not data.get('new_password'): |
|
return jsonify({"error": "Current password and new password are required"}), 400 |
|
|
|
current_password = data['current_password'] |
|
new_password = data['new_password'] |
|
|
|
|
|
user = User.find_by_id(user_id) |
|
if not user: |
|
return jsonify({"error": "User not found"}), 404 |
|
|
|
|
|
if not User.check_password(user['password'], current_password): |
|
return jsonify({"error": "Current password is incorrect"}), 400 |
|
|
|
|
|
is_valid, message = User.validate_password(new_password) |
|
if not is_valid: |
|
return jsonify({"error": message}), 400 |
|
|
|
|
|
bcrypt = get_bcrypt() |
|
new_password_hash = bcrypt.generate_password_hash(new_password).decode('utf-8') |
|
|
|
|
|
success = User.update_user(user_id, {"password": new_password_hash}) |
|
if not success: |
|
return jsonify({"error": "Failed to update password"}), 500 |
|
|
|
return jsonify({"message": "Password changed successfully"}), 200 |
|
|
|
except Exception as e: |
|
return jsonify({"error": "Failed to change password", "details": str(e)}), 500 |
|
|
|
@user_bp.route('/deactivate', methods=['PUT']) |
|
@login_required |
|
def deactivate_account(): |
|
"""Deactivate user account""" |
|
try: |
|
user_id = session['user_id'] |
|
|
|
|
|
success = User.update_user(user_id, {"is_active": False}) |
|
if not success: |
|
return jsonify({"error": "Failed to deactivate account"}), 500 |
|
|
|
|
|
session.clear() |
|
|
|
return jsonify({"message": "Account deactivated successfully"}), 200 |
|
|
|
except Exception as e: |
|
return jsonify({"error": "Failed to deactivate account", "details": str(e)}), 500 |
|
|
|
@user_bp.route('/list', methods=['GET']) |
|
@admin_required |
|
def list_users(): |
|
"""List all users (admin only)""" |
|
try: |
|
mongo = get_mongo() |
|
page = int(request.args.get('page', 1)) |
|
per_page = int(request.args.get('per_page', 10)) |
|
|
|
|
|
skip = (page - 1) * per_page |
|
|
|
|
|
users_cursor = mongo.db.users.find( |
|
{}, |
|
{"password": 0} |
|
).skip(skip).limit(per_page).sort("created_at", -1) |
|
|
|
users = [] |
|
for user in users_cursor: |
|
user['id'] = str(user['_id']) |
|
del user['_id'] |
|
users.append(user) |
|
|
|
|
|
total_users = mongo.db.users.count_documents({}) |
|
|
|
return jsonify({ |
|
"users": users, |
|
"pagination": { |
|
"page": page, |
|
"per_page": per_page, |
|
"total": total_users, |
|
"pages": (total_users + per_page - 1) // per_page |
|
} |
|
}), 200 |
|
|
|
except Exception as e: |
|
return jsonify({"error": "Failed to list users", "details": str(e)}), 500 |