Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e6dd17243 | |||
| 2124ca65b2 | |||
| bc86dc4a0d |
+24
-33
@@ -10417,15 +10417,17 @@ def notifications_view():
|
||||
admin_notifications = []
|
||||
for notif in notifications:
|
||||
is_read = username in (notif.get('ReadBy') or [])
|
||||
created_at_val = notif.get('CreatedAt')
|
||||
|
||||
row = {
|
||||
'id': str(notif.get('_id')),
|
||||
'title': notif.get('Title', 'Benachrichtigung'),
|
||||
'message': notif.get('Message', ''),
|
||||
'severity': notif.get('Severity', 'info'),
|
||||
'type': notif.get('Type', ''),
|
||||
'created_at': notif.get('CreatedAt'),
|
||||
'created_at': created_at_val if created_at_val else None,
|
||||
'is_read': is_read,
|
||||
'reference': notif.get('Reference', {}) or {},
|
||||
'reference': notif.get('Reference') or {},
|
||||
}
|
||||
if notif.get('Audience') == 'admin':
|
||||
admin_notifications.append(row)
|
||||
@@ -12132,44 +12134,33 @@ def get_optimal_image_quality(img, target_size_kb=80):
|
||||
def health_check():
|
||||
return 'OK', 200
|
||||
|
||||
|
||||
@app.route('/api/push/subscribe', methods=['POST'])
|
||||
def subscribe_to_push():
|
||||
"""
|
||||
Subscribe a user to push notifications
|
||||
|
||||
Expects JSON payload:
|
||||
{
|
||||
'subscription': {
|
||||
'endpoint': '...',
|
||||
'keys': {'p256dh': '...', 'auth': '...'}
|
||||
}
|
||||
}
|
||||
"""
|
||||
if 'username' not in session:
|
||||
return jsonify({'success': False, 'error': 'Not authenticated'}), 401
|
||||
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 401
|
||||
|
||||
data = request.get_json(silent=True) or {}
|
||||
|
||||
subscription_obj = data.get('subscription') if 'subscription' in data else data
|
||||
|
||||
if not subscription_obj or not isinstance(subscription_obj, dict):
|
||||
app.logger.error("Invalid subscription payload received")
|
||||
return jsonify({'success': False, 'error': 'Invalid payload'}), 400
|
||||
|
||||
username = session['username']
|
||||
|
||||
try:
|
||||
data = request.get_json(silent=True) or {}
|
||||
subscription = data.get('subscription')
|
||||
|
||||
if not subscription or not subscription.get('endpoint'):
|
||||
return jsonify({'success': False, 'error': 'Invalid subscription'}), 400
|
||||
|
||||
username = session['username']
|
||||
success = pn.save_push_subscription(username, subscription)
|
||||
|
||||
success = pn.save_push_subscription(username, subscription_obj)
|
||||
|
||||
if success:
|
||||
app.logger.info(f'Push subscription saved for {encrypt_text(username)}')
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Successfully subscribed to push notifications'
|
||||
})
|
||||
return jsonify({'success': True})
|
||||
else:
|
||||
return jsonify({'success': False, 'error': 'Failed to save subscription'}), 500
|
||||
|
||||
return jsonify({'success': False, 'error': 'Failed to save in DB'}), 400
|
||||
|
||||
except Exception as e:
|
||||
app.logger.error(f'Error subscribing to push: {e}')
|
||||
return jsonify({'success': False}), 500
|
||||
app.logger.error(f"Error in subscribe_to_push route: {e}")
|
||||
return jsonify({'success': False, 'error': 'Internal server error'}), 500
|
||||
|
||||
|
||||
@app.route('/api/push/unsubscribe', methods=['POST'])
|
||||
|
||||
@@ -308,8 +308,8 @@ def _send_fcm_notification(subscription, payload):
|
||||
|
||||
def _send_web_push_notification(subscription, payload):
|
||||
try:
|
||||
from pywebpush import webpush
|
||||
|
||||
from pywebpush import webpush, WebPushException
|
||||
|
||||
webpush(
|
||||
subscription_info={
|
||||
'endpoint': subscription['Endpoint'],
|
||||
@@ -319,18 +319,25 @@ def _send_web_push_notification(subscription, payload):
|
||||
vapid_private_key=VAPID_PRIVATE_KEY,
|
||||
vapid_claims={'sub': VAPID_SUBJECT},
|
||||
timeout=10,
|
||||
ttl=3600
|
||||
ttl=3600
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
except ImportError:
|
||||
logger.warning('pywebpush not installed. pip install pywebpush')
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f'Web push error: {e}')
|
||||
return False
|
||||
# HÄRTUNG: Spezifische WebPush-Fehler abfangen
|
||||
except WebPushException as ex:
|
||||
# HTTP 404 (Not Found) oder 410 (Gone) bedeuten: Abo existiert nicht mehr
|
||||
if ex.response is not None and ex.response.status_code in [404, 410]:
|
||||
logger.info(f"Subscription expired or revoked (Code {ex.response.status_code}). Marking inactive.")
|
||||
return False # False signalisiert der übergeordneten Funktion, das Abo zu deaktivieren
|
||||
|
||||
logger.error(f'Web push failed with code {ex.response.status_code if ex.response else "Unknown"}: {ex}')
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f'Unexpected Web push error: {e}')
|
||||
return False
|
||||
|
||||
def _mark_subscription_inactive(subscription_id):
|
||||
try:
|
||||
|
||||
@@ -16,4 +16,5 @@ openpyxl
|
||||
cryptography>=42.0.0
|
||||
pywebpush
|
||||
py-vapid>=1.9.0
|
||||
beautifulsoup4
|
||||
beautifulsoup4
|
||||
pywebpush
|
||||
+2
-1
@@ -16,4 +16,5 @@ openpyxl
|
||||
cryptography>=42.0.0
|
||||
pywebpush
|
||||
py-vapid>=1.9.0
|
||||
beautifulsoup4
|
||||
beautifulsoup4
|
||||
pywebpush
|
||||
Reference in New Issue
Block a user