Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d9bb62907 | |||
| 8251cd9bfd | |||
| 3ed3148b8a | |||
| 27b265eaf5 | |||
| 3571bb6f6d |
+25
-32
@@ -10373,21 +10373,39 @@ def my_borrowed_items():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/push/vapid-key', methods=['GET'])
|
||||||
|
def get_vapid_key():
|
||||||
|
"""
|
||||||
|
Returns the VAPID public key for web push subscriptions
|
||||||
|
"""
|
||||||
|
from Web.push_notifications import _get_vapid_public
|
||||||
|
if 'username' not in session:
|
||||||
|
return jsonify({'success': False, 'error': 'Not authenticated'}), 401
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not _get_vapid_public():
|
||||||
|
return jsonify({'success': False, 'error': 'VAPID public key not configured'}), 500
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
|
'publicKey': _get_vapid_public()
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
app.logger.error(f'Error getting VAPID key: {e}')
|
||||||
|
return jsonify({'success': False}), 500
|
||||||
|
|
||||||
@app.route('/notifications')
|
@app.route('/notifications')
|
||||||
def notifications_view():
|
def notifications_view():
|
||||||
"""Notification center for users and admins."""
|
"""Notification center for users and admins."""
|
||||||
|
from Web.push_notifications import _get_vapid_public
|
||||||
if 'username' not in session:
|
if 'username' not in session:
|
||||||
flash('Bitte melden Sie sich an, um Benachrichtigungen zu sehen.', 'error')
|
flash('Bitte melden Sie sich an, um Benachrichtigungen zu sehen.', 'error')
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
username = session['username']
|
username = session['username']
|
||||||
is_admin_user = False
|
|
||||||
current_permissions = us.get_effective_permissions(session['username'])
|
current_permissions = us.get_effective_permissions(session['username'])
|
||||||
|
|
||||||
if not current_permissions['actions'].get('can_manage_settings', False):
|
is_admin_user = current_permissions['actions'].get('can_manage_settings', False)
|
||||||
is_admin_user = True
|
|
||||||
else:
|
|
||||||
is_admin_user = False
|
|
||||||
|
|
||||||
client = None
|
client = None
|
||||||
try:
|
try:
|
||||||
@@ -10421,6 +10439,7 @@ def notifications_view():
|
|||||||
is_admin_user=is_admin_user,
|
is_admin_user=is_admin_user,
|
||||||
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
library_module_enabled=cfg.MODULES.is_enabled('library'),
|
||||||
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
|
||||||
|
vapid_public_key=_get_vapid_public()
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
app.logger.error(f"Error loading notifications: {exc}")
|
app.logger.error(f"Error loading notifications: {exc}")
|
||||||
@@ -12219,32 +12238,6 @@ def get_push_subscriptions():
|
|||||||
app.logger.error(f'Error getting push subscriptions: {e}')
|
app.logger.error(f'Error getting push subscriptions: {e}')
|
||||||
return jsonify({'success': False}), 500
|
return jsonify({'success': False}), 500
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/push/vapid-key', methods=['GET'])
|
|
||||||
def get_vapid_key():
|
|
||||||
"""
|
|
||||||
Get the VAPID public key for push notifications
|
|
||||||
Used by the service worker to communicate with push service
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
vapid_key = pn.VAPID_PUBLIC_KEY
|
|
||||||
if not vapid_key:
|
|
||||||
app.logger.warning('VAPID_PUBLIC_KEY not configured')
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'error': 'Push notifications not configured on server'
|
|
||||||
}), 501
|
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
'success': True,
|
|
||||||
'vapid_key': vapid_key
|
|
||||||
})
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
app.logger.error(f'Error getting VAPID key: {e}')
|
|
||||||
return jsonify({'success': False}), 500
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/push/test', methods=['POST'])
|
@app.route('/api/push/test', methods=['POST'])
|
||||||
def test_push_notification():
|
def test_push_notification():
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -40,14 +40,18 @@ try:
|
|||||||
else:
|
else:
|
||||||
vapid = Vapid.from_file(VAPID_PRIVATE_PEM)
|
vapid = Vapid.from_file(VAPID_PRIVATE_PEM)
|
||||||
|
|
||||||
# Extract public key in standard uncompressed point format encoded in URL-safe base64
|
|
||||||
raw_pub = vapid.public_key.public_bytes(
|
raw_pub = vapid.public_key.public_bytes(
|
||||||
serialization.Encoding.X962,
|
serialization.Encoding.X962,
|
||||||
serialization.PublicFormat.UncompressedPoint
|
serialization.PublicFormat.UncompressedPoint
|
||||||
)
|
)
|
||||||
|
|
||||||
VAPID_PUBLIC_KEY = b64urlencode(raw_pub).decode('utf-8')
|
encoded_pub = b64urlencode(raw_pub)
|
||||||
VAPID_PRIVATE_KEY = VAPID_PRIVATE_PEM # pywebpush accepts the file path to the private PEM
|
if isinstance(encoded_pub, bytes):
|
||||||
|
VAPID_PUBLIC_KEY = encoded_pub.decode('utf-8')
|
||||||
|
else:
|
||||||
|
VAPID_PUBLIC_KEY = encoded_pub
|
||||||
|
|
||||||
|
VAPID_PRIVATE_KEY = VAPID_PRIVATE_PEM
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Could not load or generate VAPID keys: {e}')
|
logger.error(f'Could not load or generate VAPID keys: {e}')
|
||||||
@@ -60,6 +64,9 @@ VAPID_SUBJECT = os.getenv('VAPID_SUBJECT', 'mailto:support@invario-software.de')
|
|||||||
FCM_API_KEY = os.getenv('FCM_API_KEY', '')
|
FCM_API_KEY = os.getenv('FCM_API_KEY', '')
|
||||||
|
|
||||||
|
|
||||||
|
def _get_vapid_public():
|
||||||
|
return VAPID_PUBLIC_KEY
|
||||||
|
|
||||||
def _get_username_hash(username):
|
def _get_username_hash(username):
|
||||||
"""Generates a deterministic hash for database lookups."""
|
"""Generates a deterministic hash for database lookups."""
|
||||||
if not username:
|
if not username:
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class PushNotificationManager {
|
|||||||
* Initialize push notification system
|
* Initialize push notification system
|
||||||
* Must be called after page load
|
* Must be called after page load
|
||||||
*/
|
*/
|
||||||
async init() {
|
async init(providedKey = null) {
|
||||||
if (!this.isSupported) {
|
if (!this.isSupported) {
|
||||||
console.log('Push notifications not supported in this browser');
|
console.log('Push notifications not supported in this browser');
|
||||||
return false;
|
return false;
|
||||||
@@ -49,11 +49,18 @@ class PushNotificationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch VAPID public key from server
|
// Wenn der Key direkt aus dem Template übergeben wurde, nutze diesen (spart einen Request)
|
||||||
|
if (providedKey) {
|
||||||
|
this.vapidKey = providedKey;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ansonsten: Fetch VAPID public key from server
|
||||||
const keyResponse = await fetch('/api/push/vapid-key');
|
const keyResponse = await fetch('/api/push/vapid-key');
|
||||||
if (keyResponse.ok) {
|
if (keyResponse.ok) {
|
||||||
const keyData = await keyResponse.json();
|
const keyData = await keyResponse.json();
|
||||||
this.vapidKey = keyData.vapid_key;
|
// WICHTIG: Muss exakt mit dem Python-JSON-Key übereinstimmen!
|
||||||
|
this.vapidKey = keyData.publicKey;
|
||||||
} else {
|
} else {
|
||||||
console.warn('Failed to fetch VAPID key');
|
console.warn('Failed to fetch VAPID key');
|
||||||
return false;
|
return false;
|
||||||
@@ -324,7 +331,7 @@ const pushNotificationManager = new PushNotificationManager();
|
|||||||
/**
|
/**
|
||||||
* Show notification subscription UI (typically in settings)
|
* Show notification subscription UI (typically in settings)
|
||||||
*/
|
*/
|
||||||
function showPushNotificationSettings() {
|
function showPushNotificationSettings(vapidPublicKey) {
|
||||||
const container = document.getElementById('push-notification-settings');
|
const container = document.getElementById('push-notification-settings');
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
@@ -350,9 +357,9 @@ function showPushNotificationSettings() {
|
|||||||
|
|
||||||
container.innerHTML = html;
|
container.innerHTML = html;
|
||||||
|
|
||||||
// Set up button handler
|
// Set up button handler and pass the VAPID public key to init()
|
||||||
const toggleBtn = document.getElementById('toggle-push-btn');
|
const toggleBtn = document.getElementById('toggle-push-btn');
|
||||||
pushNotificationManager.init().then(() => {
|
pushNotificationManager.init(vapidPublicKey).then(() => {
|
||||||
updatePushStatus();
|
updatePushStatus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
if (typeof showPushNotificationSettings === 'function') {
|
if (typeof showPushNotificationSettings === 'function') {
|
||||||
showPushNotificationSettings();
|
showPushNotificationSettings('{{ vapid_public_key }}');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user