Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e6dd17243 | |||
| 2124ca65b2 | |||
| bc86dc4a0d |
+24
-33
@@ -10417,15 +10417,17 @@ def notifications_view():
|
|||||||
admin_notifications = []
|
admin_notifications = []
|
||||||
for notif in notifications:
|
for notif in notifications:
|
||||||
is_read = username in (notif.get('ReadBy') or [])
|
is_read = username in (notif.get('ReadBy') or [])
|
||||||
|
created_at_val = notif.get('CreatedAt')
|
||||||
|
|
||||||
row = {
|
row = {
|
||||||
'id': str(notif.get('_id')),
|
'id': str(notif.get('_id')),
|
||||||
'title': notif.get('Title', 'Benachrichtigung'),
|
'title': notif.get('Title', 'Benachrichtigung'),
|
||||||
'message': notif.get('Message', ''),
|
'message': notif.get('Message', ''),
|
||||||
'severity': notif.get('Severity', 'info'),
|
'severity': notif.get('Severity', 'info'),
|
||||||
'type': notif.get('Type', ''),
|
'type': notif.get('Type', ''),
|
||||||
'created_at': notif.get('CreatedAt'),
|
'created_at': created_at_val if created_at_val else None,
|
||||||
'is_read': is_read,
|
'is_read': is_read,
|
||||||
'reference': notif.get('Reference', {}) or {},
|
'reference': notif.get('Reference') or {},
|
||||||
}
|
}
|
||||||
if notif.get('Audience') == 'admin':
|
if notif.get('Audience') == 'admin':
|
||||||
admin_notifications.append(row)
|
admin_notifications.append(row)
|
||||||
@@ -12132,44 +12134,33 @@ def get_optimal_image_quality(img, target_size_kb=80):
|
|||||||
def health_check():
|
def health_check():
|
||||||
return 'OK', 200
|
return 'OK', 200
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/push/subscribe', methods=['POST'])
|
@app.route('/api/push/subscribe', methods=['POST'])
|
||||||
def subscribe_to_push():
|
def subscribe_to_push():
|
||||||
"""
|
|
||||||
Subscribe a user to push notifications
|
|
||||||
|
|
||||||
Expects JSON payload:
|
|
||||||
{
|
|
||||||
'subscription': {
|
|
||||||
'endpoint': '...',
|
|
||||||
'keys': {'p256dh': '...', 'auth': '...'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
if 'username' not in session:
|
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:
|
try:
|
||||||
data = request.get_json(silent=True) or {}
|
success = pn.save_push_subscription(username, subscription_obj)
|
||||||
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)
|
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
app.logger.info(f'Push subscription saved for {encrypt_text(username)}')
|
return jsonify({'success': True})
|
||||||
return jsonify({
|
|
||||||
'success': True,
|
|
||||||
'message': 'Successfully subscribed to push notifications'
|
|
||||||
})
|
|
||||||
else:
|
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:
|
except Exception as e:
|
||||||
app.logger.error(f'Error subscribing to push: {e}')
|
app.logger.error(f"Error in subscribe_to_push route: {e}")
|
||||||
return jsonify({'success': False}), 500
|
return jsonify({'success': False, 'error': 'Internal server error'}), 500
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/push/unsubscribe', methods=['POST'])
|
@app.route('/api/push/unsubscribe', methods=['POST'])
|
||||||
|
|||||||
@@ -308,8 +308,8 @@ def _send_fcm_notification(subscription, payload):
|
|||||||
|
|
||||||
def _send_web_push_notification(subscription, payload):
|
def _send_web_push_notification(subscription, payload):
|
||||||
try:
|
try:
|
||||||
from pywebpush import webpush
|
from pywebpush import webpush, WebPushException
|
||||||
|
|
||||||
webpush(
|
webpush(
|
||||||
subscription_info={
|
subscription_info={
|
||||||
'endpoint': subscription['Endpoint'],
|
'endpoint': subscription['Endpoint'],
|
||||||
@@ -319,18 +319,25 @@ def _send_web_push_notification(subscription, payload):
|
|||||||
vapid_private_key=VAPID_PRIVATE_KEY,
|
vapid_private_key=VAPID_PRIVATE_KEY,
|
||||||
vapid_claims={'sub': VAPID_SUBJECT},
|
vapid_claims={'sub': VAPID_SUBJECT},
|
||||||
timeout=10,
|
timeout=10,
|
||||||
ttl=3600
|
ttl=3600
|
||||||
)
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
logger.warning('pywebpush not installed. pip install pywebpush')
|
logger.warning('pywebpush not installed. pip install pywebpush')
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
# HÄRTUNG: Spezifische WebPush-Fehler abfangen
|
||||||
logger.error(f'Web push error: {e}')
|
except WebPushException as ex:
|
||||||
return False
|
# 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):
|
def _mark_subscription_inactive(subscription_id):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -16,4 +16,5 @@ openpyxl
|
|||||||
cryptography>=42.0.0
|
cryptography>=42.0.0
|
||||||
pywebpush
|
pywebpush
|
||||||
py-vapid>=1.9.0
|
py-vapid>=1.9.0
|
||||||
beautifulsoup4
|
beautifulsoup4
|
||||||
|
pywebpush
|
||||||
+2
-1
@@ -16,4 +16,5 @@ openpyxl
|
|||||||
cryptography>=42.0.0
|
cryptography>=42.0.0
|
||||||
pywebpush
|
pywebpush
|
||||||
py-vapid>=1.9.0
|
py-vapid>=1.9.0
|
||||||
beautifulsoup4
|
beautifulsoup4
|
||||||
|
pywebpush
|
||||||
Reference in New Issue
Block a user