from flask import Blueprint, request, jsonify, current_app from tinydb import Query from api.utils import get_validated_user_id from db.push_subscriptions import upsert_subscription, delete_by_endpoint from db.db import users_db push_subscription_api = Blueprint('push_subscription_api', __name__) @push_subscription_api.route('/push-vapid-key', methods=['GET']) def get_vapid_public_key(): """Return the VAPID public key for the frontend to use when subscribing.""" public_key = current_app.config.get('VAPID_PUBLIC_KEY', '') return jsonify({'public_key': public_key}), 200 @push_subscription_api.route('/push-subscription', methods=['POST']) def subscribe(): """Upsert a push subscription for the current user.""" user_id = get_validated_user_id() if not user_id: return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401 data = request.get_json() or {} endpoint = data.get('endpoint') keys = data.get('keys') timezone_str = data.get('timezone') if not endpoint or not isinstance(keys, dict): return jsonify({'error': 'endpoint and keys are required', 'code': 'MISSING_FIELDS'}), 400 if 'p256dh' not in keys or 'auth' not in keys: return jsonify({'error': 'keys must contain p256dh and auth', 'code': 'MISSING_FIELDS'}), 400 sub = upsert_subscription(user_id=user_id, endpoint=endpoint, keys=keys) # Update user timezone if provided if timezone_str: UserQ = Query() users_db.update({'timezone': timezone_str}, UserQ.id == user_id) return jsonify({'message': 'Subscription saved', 'id': sub.id}), 200 @push_subscription_api.route('/push-subscription', methods=['DELETE']) def unsubscribe(): """Remove a push subscription for the current user by endpoint.""" user_id = get_validated_user_id() if not user_id: return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401 data = request.get_json() or {} endpoint = data.get('endpoint') if not endpoint: return jsonify({'error': 'endpoint is required', 'code': 'MISSING_FIELDS'}), 400 removed = delete_by_endpoint(user_id=user_id, endpoint=endpoint) return jsonify({'message': 'Subscription removed', 'removed': removed}), 200