Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7368d82fc4 | |||
| 3e5e243ddf | |||
| 8176cea8fe | |||
| b71f2e9089 | |||
| 1331afa4da | |||
| 5a2d703bc7 |
@@ -12241,9 +12241,6 @@ def test_push_notification():
|
||||
if 'username' not in session:
|
||||
return jsonify({'success': False, 'error': 'Not authenticated'}), 401
|
||||
|
||||
if not us.is_admin(session['username']):
|
||||
return jsonify({'success': False, 'error': 'Admin access required'}), 403
|
||||
|
||||
try:
|
||||
data = request.get_json(silent=True) or {}
|
||||
target_user = data.get('target_user', session['username'])
|
||||
|
||||
@@ -37,14 +37,14 @@ def send(email: list | str, subject: str, note: str, sender: str) -> bool:
|
||||
<tr>
|
||||
<td>
|
||||
<p style="margin:0 0 12px 0;">Mit freundlichen Grüßen</p>
|
||||
<p style="margin:0;"><strong style="font-size:16px;">Automatisierter Email Verteiler für die Schule: {cfg.get_school_info().get("name")}</strong><br></p>
|
||||
<p style="margin:0;"><strong style="font-size:16px;">Automatisierter Email Verteiler für die Schule: {cfg.get_school_info().get("name")}</strong><br></p><br>
|
||||
<p style="margin:12px 0 0 0;"><strong>Invario UG</strong><br>Am Sportplatz 10<br>83052 Bruckmühl</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
|
||||
text_content = f"{body_message}\n\nMit freundlichen Grüßen\n{sender}\nInvario UG"
|
||||
text_content = f"{body_message}\n\nMit freundlichen Grüßen\n{sender}\n"
|
||||
|
||||
html_content = f"""
|
||||
<html>
|
||||
|
||||
@@ -252,8 +252,8 @@ def new(date_start: str, date_end: str, time_span: list, slots, slot_length, use
|
||||
if calendar_link:
|
||||
email_body += f"\n\nKalendereintrag: {calendar_link}"
|
||||
|
||||
if normalized_mail and cfg.EMAIL_ENABLED:
|
||||
mail_service.send(normalized_mail, subject, email_body)
|
||||
#if normalized_mail and cfg.EMAIL_ENABLED:
|
||||
mail_service.send(normalized_mail, subject, email_body, f"Terminplanungssystem {cfg.SCHOOL_INFO_DEFAULT.get("name")}")
|
||||
|
||||
return {
|
||||
'appointment_id': id_str,
|
||||
|
||||
+18
-12
@@ -122,29 +122,33 @@ def get_user_subscriptions(username):
|
||||
|
||||
|
||||
def save_push_subscription(username, subscription_obj):
|
||||
"""Save a new push subscription for a user with field-level encryption."""
|
||||
import traceback # Hilft uns, Fehler genau zu sehen
|
||||
try:
|
||||
print("--- DEBUG PUSH PAYLOAD ---")
|
||||
print(subscription_obj)
|
||||
|
||||
endpoint = subscription_obj.get('endpoint')
|
||||
keys = subscription_obj.get('keys', {})
|
||||
|
||||
if not endpoint or not keys.get('p256dh') or not keys.get('auth'):
|
||||
logger.warning(f'Invalid subscription object for {username}: missing endpoint or keys')
|
||||
print(
|
||||
f"DEBUG FEHLER: Keys fehlen! Endpoint: {bool(endpoint)}, p256dh: {bool(keys.get('p256dh'))}, auth: {bool(keys.get('auth'))}")
|
||||
return False
|
||||
|
||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||
db = client[cfg.MONGODB_DB]
|
||||
subs_col = get_push_subscriptions_collection(db)
|
||||
|
||||
|
||||
# Create unique hash of subscription using plaintext data to avoid duplicates
|
||||
sub_hash = hashlib.shake_256(
|
||||
f"{username}:{endpoint}".encode('utf-8')
|
||||
).hexdigest()
|
||||
|
||||
).hexdigest(32)
|
||||
|
||||
# Check if subscription already exists by Hash
|
||||
existing = subs_col.find_one({
|
||||
'SubscriptionHash': sub_hash
|
||||
})
|
||||
|
||||
|
||||
if existing:
|
||||
subs_col.update_one(
|
||||
{'_id': existing['_id']},
|
||||
@@ -156,10 +160,10 @@ def save_push_subscription(username, subscription_obj):
|
||||
logger.info('Updated existing push subscription')
|
||||
client.close()
|
||||
return True
|
||||
|
||||
|
||||
# Format keys as JSON string for your encrypt_text module
|
||||
keys_str = json.dumps(subscription_obj.get('keys', {}))
|
||||
|
||||
|
||||
# Save new subscription, encrypting sensitive fields
|
||||
subscription_doc = {
|
||||
'UsernameHash': _get_username_hash(username),
|
||||
@@ -172,14 +176,16 @@ def save_push_subscription(username, subscription_obj):
|
||||
'LastUsed': datetime.datetime.now(),
|
||||
'UserAgent': subscription_obj.get('userAgent', ''),
|
||||
}
|
||||
|
||||
|
||||
subs_col.insert_one(subscription_doc)
|
||||
logger.info('Saved new encrypted push subscription')
|
||||
client.close()
|
||||
return True
|
||||
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f'Error saving push subscription: {e}')
|
||||
print(f"DEBUG ABSTURZ in save_push_subscription: {e}")
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
@@ -191,7 +197,7 @@ def remove_push_subscription(username, endpoint):
|
||||
|
||||
sub_hash = hashlib.shake_256(
|
||||
f"{username}:{endpoint}".encode('utf-8')
|
||||
).hexdigest()
|
||||
).hexdigest(32)
|
||||
|
||||
result = subs_col.update_one(
|
||||
{'SubscriptionHash': sub_hash},
|
||||
|
||||
@@ -161,15 +161,19 @@ class PushNotificationManager {
|
||||
try {
|
||||
const subscription = await this.serviceWorkerRegistration.pushManager.getSubscription();
|
||||
if (!subscription) {
|
||||
console.warn('No active push subscription');
|
||||
return true; // Bereits deaktiviert
|
||||
return true;
|
||||
}
|
||||
|
||||
// Best-Effort: Dem Server Bescheid geben (wir ignorieren absichtlich,
|
||||
// falls der Server das Abo nicht mehr kennt)
|
||||
await this.removeSubscriptionFromServer(subscription);
|
||||
// Best-Effort: Server benachrichtigen (Eigener try/catch Block!)
|
||||
try {
|
||||
await this.removeSubscriptionFromServer(subscription);
|
||||
} catch (serverError) {
|
||||
// Fehler vom Server ignorieren wir absichtlich.
|
||||
// Das Skript läuft weiter, statt hier abzubrechen!
|
||||
console.warn('Server-Abmeldung fehlgeschlagen, lösche lokal trotzdem:', serverError);
|
||||
}
|
||||
|
||||
// WICHTIG: Das Abo im Browser immer zwingend löschen!
|
||||
// WICHTIG: Das hier wird jetzt garantiert ausgeführt
|
||||
await subscription.unsubscribe();
|
||||
return true;
|
||||
|
||||
|
||||
@@ -1148,7 +1148,7 @@
|
||||
{% if current_permissions.pages.get('tutorial_page', False) %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('tutorial_page') }}">Tutorial</a></li>
|
||||
{% endif %}
|
||||
{% if current_permissions.pages.get('admin_school_settings', False) %}
|
||||
{% if current_permissions.actions.get('can_manage_settings', False) %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin_school_settings') }}">Schulstammdaten</a></li>
|
||||
{% endif %}
|
||||
{% if current_permissions.actions.get('can_view_logs', False) or current_permissions.pages.get('admin_audit_dashboard', False) %}
|
||||
@@ -1257,7 +1257,7 @@
|
||||
{% if current_permissions.pages.get('manage_locations', False) %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('manage_locations') }}">Orte verwalten</a></li>
|
||||
{% endif %}
|
||||
{% if current_permissions.pages.get('admin_school_settings', False) %}
|
||||
{% if current_permissions.actions.get('can_manage_settings', False) %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin_school_settings') }}">Schulstammdaten</a></li>
|
||||
{% endif %}
|
||||
{% if current_permissions.pages.get('admin_borrowings', False) %}
|
||||
@@ -1379,7 +1379,7 @@
|
||||
<li><a class="dropdown-item" href="{{ url_for('student_cards_admin') }}">Bibliotheksausweis</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if current_permissions.pages.get('admin_school_settings', False) %}
|
||||
{% if current_permissions.actions.get('can_manage_settings', False) %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin_school_settings') }}">Schulstammdaten</a></li>
|
||||
{% endif %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
@@ -1698,7 +1698,7 @@
|
||||
<option value="Orte verwalten"></option>
|
||||
{% endif %}
|
||||
|
||||
{% if current_permissions.pages.get('admin_school_settings', False) %}
|
||||
{% if current_permissions.actions.get('can_manage_settings', False) %}
|
||||
<option value="Schulstammdaten"></option>
|
||||
{% endif %}
|
||||
|
||||
@@ -1823,7 +1823,7 @@
|
||||
{ label: 'Orte verwalten', keywords: ['orte verwalten', 'orte', 'location'], url: {{ url_for('manage_locations')|tojson }} },
|
||||
{% endif %}
|
||||
|
||||
{% if current_permissions.pages.get('admin_school_settings', False) %}
|
||||
{% if current_permissions.actions.get('can_manage_settings', False) %}
|
||||
{ label: 'Schulstammdaten', keywords: ['schule', 'settings', 'stammdaten', 'school settings'], url: {{ url_for('admin_school_settings')|tojson }} },
|
||||
{% endif %}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user