milk_manager/milk_app/devices.py
2025-04-09 20:34:32 +08:00

79 lines
3.3 KiB
Python

from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from .database import db, PushDevice, User
device_bp = Blueprint('devices', __name__, url_prefix='/api/devices')
@device_bp.route('', methods=['POST'])
@jwt_required()
def register_device():
current_user_id = get_jwt_identity()
data = request.get_json()
if not data: return jsonify({"error": "Request must be JSON"}), 400
device_type = data.get('type')
token = data.get('token')
if not device_type or not token:
return jsonify({"error": "Missing 'type' or 'token'"}), 400
if device_type not in ['web', 'ios', 'android']:
return jsonify({"error": "Invalid device type"}), 400
# Check if token already exists to prevent duplicates
existing = PushDevice.query.filter_by(token=token).first()
if existing:
# Optional: Update user_id if token somehow got registered by another user?
# Or just return OK indicating it's known
if existing.user_id != current_user_id:
# Decide handling: update owner or error? Let's update.
existing.user_id = current_user_id
db.session.commit()
print(f"Warning: Push token {token[:10]}... re-assigned to user {current_user_id}")
return jsonify({"message": "Device already registered"}), 200
new_device = PushDevice(
user_id=current_user_id,
device_type=device_type,
token=token
)
db.session.add(new_device)
try:
db.session.commit()
return jsonify({"message": "Device registered successfully"}), 201
except Exception as e:
db.session.rollback()
# Could be unique constraint violation if race condition, or DB error
print(f"Error registering device: {e}")
# Check again if it exists now (due to race condition)
existing = PushDevice.query.filter_by(token=token).first()
if existing: return jsonify({"message": "Device already registered"}), 200
return jsonify({"error": "Failed to register device"}), 500
@device_bp.route('/<string:token_prefix>', methods=['DELETE'])
@jwt_required()
def unregister_device(token_prefix):
# Note: Deleting by full token in URL can be problematic (length, encoding).
# A better approach might be POST /api/devices/unregister { "token": "..." }
# Or require the client to store the device ID returned on registration and use that.
# For simplicity now, we'll assume we search by token.
current_user_id = get_jwt_identity()
# This is inefficient if tokens are long. A dedicated device ID is better.
# Let's simulate finding based on a prefix if needed, but ideally use full token from body
# device = PushDevice.query.filter(PushDevice.token.like(f'{token_prefix}%'), PushDevice.user_id==current_user_id).first()
# --- Alternative using request body ---
data = request.get_json()
token_to_delete = data.get('token') if data else None
if not token_to_delete:
return jsonify({"error": "Token required in request body for deletion"}), 400
device = PushDevice.query.filter_by(token=token_to_delete, user_id=current_user_id).first()
if not device:
return jsonify({"error": "Device not found or not owned by user"}), 404
db.session.delete(device)
db.session.commit()
return '', 204