From 37694dde09c8b0f4f3b2c40e50bab3a73485dd02 Mon Sep 17 00:00:00 2001 From: MarekWo Date: Mon, 2 Mar 2026 08:14:10 +0100 Subject: [PATCH] fix(contacts): remove from pending list after approve + add reject/clear approve_contact now removes the contact from mc.pending_contacts after successful approval. Added reject_contact (remove without adding) and clear_pending_contacts methods with API endpoints. Co-Authored-By: Claude Opus 4.6 --- app/device_manager.py | 27 +++++++++++++++++++++++++++ app/routes/api.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/app/device_manager.py b/app/device_manager.py index af508dd..bae0f1e 100644 --- a/app/device_manager.py +++ b/app/device_manager.py @@ -827,11 +827,38 @@ class DeviceManager: last_advert=last_advert_val, source='device', ) + # Remove from pending list after successful approval + self.mc.pending_contacts.pop(pubkey, None) return {'success': True, 'message': 'Contact approved'} except Exception as e: logger.error(f"Failed to approve contact: {e}") return {'success': False, 'error': str(e)} + def reject_contact(self, pubkey: str) -> Dict: + """Reject a pending contact (remove from pending list without adding).""" + if not self.is_connected: + return {'success': False, 'error': 'Device not connected'} + + try: + removed = self.mc.pending_contacts.pop(pubkey, None) + if removed: + return {'success': True, 'message': 'Contact rejected'} + return {'success': False, 'error': 'Contact not in pending list'} + except Exception as e: + logger.error(f"Failed to reject contact: {e}") + return {'success': False, 'error': str(e)} + + def clear_pending_contacts(self) -> Dict: + """Clear all pending contacts.""" + try: + count = len(self.mc.pending_contacts) if self.mc and self.mc.pending_contacts else 0 + if self.mc and self.mc.pending_contacts is not None: + self.mc.pending_contacts.clear() + return {'success': True, 'message': f'Cleared {count} pending contacts'} + except Exception as e: + logger.error(f"Failed to clear pending contacts: {e}") + return {'success': False, 'error': str(e)} + def get_battery(self) -> Optional[Dict]: """Get battery status.""" if not self.is_connected: diff --git a/app/routes/api.py b/app/routes/api.py index f71713e..da0c39e 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -2678,6 +2678,42 @@ def approve_pending_contact_api(): }), 500 +@api_bp.route('/contacts/pending/reject', methods=['POST']) +def reject_pending_contact_api(): + """Reject a pending contact (remove from pending list without adding).""" + try: + data = request.get_json() + if not data or 'public_key' not in data: + return jsonify({'success': False, 'error': 'Missing required field: public_key'}), 400 + + dm = _get_dm() + if not dm: + return jsonify({'success': False, 'error': 'Device not connected'}), 503 + + result = dm.reject_contact(data['public_key']) + status = 200 if result['success'] else 500 + return jsonify(result), status + except Exception as e: + logger.error(f"Error rejecting pending contact: {e}") + return jsonify({'success': False, 'error': str(e)}), 500 + + +@api_bp.route('/contacts/pending/clear', methods=['POST']) +def clear_pending_contacts_api(): + """Clear all pending contacts.""" + try: + dm = _get_dm() + if not dm: + return jsonify({'success': False, 'error': 'Device not connected'}), 503 + + result = dm.clear_pending_contacts() + status = 200 if result['success'] else 500 + return jsonify(result), status + except Exception as e: + logger.error(f"Error clearing pending contacts: {e}") + return jsonify({'success': False, 'error': str(e)}), 500 + + @api_bp.route('/device/settings', methods=['GET']) def get_device_settings_api(): """