Compare commits

..

6 Commits

6 changed files with 69 additions and 63 deletions
+25 -32
View File
@@ -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')
def notifications_view():
"""Notification center for users and admins."""
from Web.push_notifications import _get_vapid_public
if 'username' not in session:
flash('Bitte melden Sie sich an, um Benachrichtigungen zu sehen.', 'error')
return redirect(url_for('login'))
username = session['username']
is_admin_user = False
current_permissions = us.get_effective_permissions(session['username'])
if not current_permissions['actions'].get('can_manage_settings', False):
is_admin_user = True
else:
is_admin_user = False
is_admin_user = current_permissions['actions'].get('can_manage_settings', False)
client = None
try:
@@ -10421,6 +10439,7 @@ def notifications_view():
is_admin_user=is_admin_user,
library_module_enabled=cfg.MODULES.is_enabled('library'),
student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards'),
vapid_public_key=_get_vapid_public()
)
except Exception as 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}')
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'])
def test_push_notification():
"""
+1 -1
View File
@@ -300,7 +300,7 @@ def _match_student_cards(path):
def _match_mail(path):
if not path: return False
return path.startswith(('/'))
return path.startswith(('/configure'))
# Register core modules into the pipeline
MODULES.register('inventory', INVENTORY_MODULE_ENABLED, _match_inventory)
+38 -25
View File
@@ -20,40 +20,53 @@ logger = logging.getLogger(__name__)
# VAPID keys for push notifications
VAPID_PUBLIC_KEY = os.getenv('VAPID_PUBLIC_KEY', '')
VAPID_PRIVATE_KEY = os.getenv('VAPID_PRIVATE_KEY', '')
VAPID_SUBJECT = os.getenv('VAPID_SUBJECT', f'mailto:admin@{os.getenv("SERVER_NAME", "localhost")}')
VAPID_SUBJECT = os.getenv('VAPID_SUBJECT', f'mailto:support@invario-software.de')
# VAPID keys file paths
VAPID_PRIVATE_PEM = os.path.join(os.path.dirname(__file__), 'vapid_private.pem')
VAPID_PUBLIC_PEM = os.path.join(os.path.dirname(__file__), 'vapid_public.pem')
# Auto-generate VAPID keys if none are provided
if not VAPID_PUBLIC_KEY or not VAPID_PRIVATE_KEY:
try:
from py_vapid import Vapid, b64urlencode
from cryptography.hazmat.primitives import serialization
# Load or auto-generate VAPID keys
try:
from py_vapid import Vapid, b64urlencode
from cryptography.hazmat.primitives import serialization
if not os.path.exists(VAPID_PRIVATE_PEM) or not os.path.exists(VAPID_PUBLIC_PEM):
vapid = Vapid()
if not os.path.exists(VAPID_PRIVATE_PEM):
vapid.generate_keys()
vapid.save_key(VAPID_PRIVATE_PEM)
vapid.save_public_key(VAPID_PUBLIC_PEM)
logger.info("Auto-generated new VAPID keys")
else:
vapid = Vapid.from_file(VAPID_PRIVATE_PEM)
raw_pub = vapid.public_key.public_bytes(
serialization.Encoding.X962,
serialization.PublicFormat.UncompressedPoint
)
VAPID_PUBLIC_KEY = b64urlencode(raw_pub).decode('utf-8')
VAPID_PRIVATE_KEY = VAPID_PRIVATE_PEM
except Exception as e:
logger.error(f'Could not load or generate VAPID keys: {e}')
vapid.generate_keys()
vapid.save_key(VAPID_PRIVATE_PEM)
vapid.save_public_key(VAPID_PUBLIC_PEM)
logger.info("Auto-generated new VAPID keys")
else:
vapid = Vapid.from_file(VAPID_PRIVATE_PEM)
raw_pub = vapid.public_key.public_bytes(
serialization.Encoding.X962,
serialization.PublicFormat.UncompressedPoint
)
encoded_pub = b64urlencode(raw_pub)
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:
logger.error(f'Could not load or generate VAPID keys: {e}')
VAPID_PUBLIC_KEY = os.getenv('VAPID_PUBLIC_KEY', '')
VAPID_PRIVATE_KEY = os.getenv('VAPID_PRIVATE_KEY', '')
VAPID_SUBJECT = os.getenv('VAPID_SUBJECT', 'mailto:support@invario-software.de')
# Push service endpoint (typically Firebase or Web Push Service)
FCM_API_KEY = os.getenv('FCM_API_KEY', '') # Firebase API key
FCM_API_KEY = os.getenv('FCM_API_KEY', '')
def _get_vapid_public():
return VAPID_PUBLIC_KEY
def _get_username_hash(username):
"""Generates a deterministic hash for database lookups."""
if not username:
+3 -3
View File
@@ -324,7 +324,7 @@ const pushNotificationManager = new PushNotificationManager();
/**
* Show notification subscription UI (typically in settings)
*/
function showPushNotificationSettings() {
function showPushNotificationSettings(vapidPublicKey) {
const container = document.getElementById('push-notification-settings');
if (!container) return;
@@ -350,9 +350,9 @@ function showPushNotificationSettings() {
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');
pushNotificationManager.init().then(() => {
pushNotificationManager.init(vapidPublicKey).then(() => {
updatePushStatus();
});
+1 -1
View File
@@ -1371,8 +1371,8 @@
await loadLibraryItems(); // Daten neu laden
// renderTable(); // Ggf. Tabelle neu rendern
} else {
closeEditLibraryModal();
await loadLibraryItems();
closeEditLibraryModal();
}
} catch (error) {
console.error('Update failed:', error);
+1 -1
View File
@@ -89,7 +89,7 @@
<script>
document.addEventListener('DOMContentLoaded', function() {
if (typeof showPushNotificationSettings === 'function') {
showPushNotificationSettings();
showPushNotificationSettings('{{ vapid_public_key }}');
}
});
</script>