diff --git a/srv/tesm/VERSION b/srv/tesm/VERSION index c813fe1..3c43790 100644 --- a/srv/tesm/VERSION +++ b/srv/tesm/VERSION @@ -1 +1 @@ -1.2.5 +1.2.6 diff --git a/srv/tesm/app.py b/srv/tesm/app.py index e60666a..b6544c8 100644 --- a/srv/tesm/app.py +++ b/srv/tesm/app.py @@ -326,6 +326,10 @@ PERMISSIONS = { "label": "Systemeinstellungen", "rows": {"view": "settings_system.view", "edit": "settings_system.edit"}, }, + "settings_license": { + "label": "Lizenz", + "rows": {"view": "settings_license.view", "edit": "settings_license.edit"}, + }, "settings_importexport": { "label": "Im-/Export", "rows": { @@ -392,6 +396,8 @@ PERMISSION_LABELS = { "groups.view": "Gruppen lesen", "groups.create": "Gruppen anlegen", "groups.edit": "Gruppen ändern (inkl. Löschen)", "settings_system.view": "Systemeinstellungen lesen", "settings_system.edit": "Systemeinstellungen ändern", + "settings_license.view": "Lizenzstatus ansehen", + "settings_license.edit": "Lizenzdatei hochladen sowie Lizenz aktivieren/deaktivieren (online oder per Code)", "settings_importexport.view": "Im-/Export-Seite ansehen", "settings_importexport.edit": "Daten importieren", "settings_importexport.export": "Daten exportieren (Export-Datei enthält Passwörter im Klartext)", @@ -486,10 +492,11 @@ def _nav_key_visible(key, user): if key == "settings_system": return user.can_view_settings_system if key == "settings_license": - # Immer erreichbar für jeden mit Systemeinstellungen-Leserecht -- - # muss auch OHNE Lizenz sichtbar bleiben, sonst könnte niemand - # jemals eine erste Lizenz hochladen/aktivieren. - return user.can_view_settings_system + # Eigenes Recht (settings_license.view), unabhängig von + # settings_system -- muss auch OHNE eine aktive Lizenz sichtbar + # bleiben (das ist eine andere Prüfung, siehe license_active()), + # sonst könnte niemand jemals eine erste Lizenz hochladen/aktivieren. + return user.can_view_settings_license if key == "settings_importexport": return user.can_view_settings_importexport if key == "settings_dhcp": @@ -726,6 +733,10 @@ class User(UserMixin): def can_view_settings_system(self): return self.has_permission("settings_system.view") + @property + def can_view_settings_license(self): + return self.has_permission("settings_license.view") + @property def can_view_settings_importexport(self): return self.has_any_permission([ @@ -1146,6 +1157,32 @@ def _ensure_schema(): "INSERT OR IGNORE INTO settings (key, value) VALUES (?, '1')", (_migration_key_v2,) ) + _migration_key_license_perm = "_migrated_settings_license_permission_v1" + if not conn.execute("SELECT 1 FROM settings WHERE key=?", (_migration_key_license_perm,)).fetchone(): + # "Lizenz" (settings_license) hatte bislang KEIN eigenes Recht -- + # die Seite lief komplett über settings_system.view/.edit mit. + # Backfill: jede Gruppe, die settings_system.view/.edit bereits + # hatte, bekommt automatisch das neue, gespiegelte + # settings_license.view/.edit dazu -- ohne diesen Schritt würden + # bestehende Gruppen beim Update stillschweigend den Zugriff auf + # die Lizenzseite verlieren, den sie vorher implizit hatten. + _system_to_license = { + "settings_system.view": "settings_license.view", + "settings_system.edit": "settings_license.edit", + } + for system_perm, license_perm in _system_to_license.items(): + rows = conn.execute( + "SELECT DISTINCT group_id FROM group_permissions WHERE permission=?", (system_perm,) + ).fetchall() + for row in rows: + conn.execute( + "INSERT OR IGNORE INTO group_permissions (group_id, permission) VALUES (?, ?)", + (row["group_id"], license_perm), + ) + conn.execute( + "INSERT OR IGNORE INTO settings (key, value) VALUES (?, '1')", (_migration_key_license_perm,) + ) + _migration_key_old_logs = "_cleaned_up_legacy_rpi_log_files_v1" if not conn.execute("SELECT 1 FROM settings WHERE key=?", (_migration_key_old_logs,)).fetchone(): for stale_log in glob.glob("/var/log/rpi-*.log"): @@ -4469,7 +4506,7 @@ def settings(): @app.route("/settings/license") @login_required def settings_license(): - if not current_user.can_view_settings_system: + if not current_user.can_view_settings_license: flash("Keine Berechtigung, die Lizenz anzusehen.", "danger") return redirect(url_for("index")) pending_raw = get_setting("license_pending_request", "") @@ -4492,7 +4529,7 @@ def settings_license(): @app.route("/settings/license/upload", methods=["POST"]) @login_required def license_upload(): - if not current_user.has_permission("settings_system.edit"): + if not current_user.has_permission("settings_license.edit"): flash("Keine Berechtigung, die Lizenz zu ändern.", "danger") return redirect(url_for("settings_license")) uploaded = request.files.get("license_file") @@ -4585,7 +4622,7 @@ def _license_handshake_confirm(action, success_setting_fn, success_log_action, s @app.route("/settings/license/activate", methods=["POST"]) @login_required def license_activate(): - if not current_user.has_permission("settings_system.edit"): + if not current_user.has_permission("settings_license.edit"): flash("Keine Berechtigung, die Lizenz zu aktivieren.", "danger") return redirect(url_for("settings_license")) if not _license_state.get("file") or not _license_state.get("valid"): @@ -4614,7 +4651,7 @@ def license_activate(): @app.route("/settings/license/activate/confirm", methods=["POST"]) @login_required def license_activate_confirm(): - if not current_user.has_permission("settings_system.edit"): + if not current_user.has_permission("settings_license.edit"): flash("Keine Berechtigung, die Lizenz zu aktivieren.", "danger") return redirect(url_for("settings_license")) @@ -4640,7 +4677,7 @@ def license_activate_confirm(): @app.route("/settings/license/deactivate", methods=["POST"]) @login_required def license_deactivate(): - if not current_user.has_permission("settings_system.edit"): + if not current_user.has_permission("settings_license.edit"): flash("Keine Berechtigung, die Lizenz zu deaktivieren.", "danger") return redirect(url_for("settings_license")) if not _license_state.get("file") or not license_activated(): @@ -4660,7 +4697,7 @@ def license_deactivate(): @app.route("/settings/license/deactivate/confirm", methods=["POST"]) @login_required def license_deactivate_confirm(): - if not current_user.has_permission("settings_system.edit"): + if not current_user.has_permission("settings_license.edit"): flash("Keine Berechtigung, die Lizenz zu deaktivieren.", "danger") return redirect(url_for("settings_license")) diff --git a/srv/tesm/templates/settings_license.html b/srv/tesm/templates/settings_license.html index 84a6059..76dae04 100644 --- a/srv/tesm/templates/settings_license.html +++ b/srv/tesm/templates/settings_license.html @@ -1,6 +1,6 @@ {% extends "base.html" %} {% set active_page = "settings_license" %} -{% set can_edit = current_user.has_permission('settings_system.edit') %} +{% set can_edit = current_user.has_permission('settings_license.edit') %} {% block page_title %}Lizenz{% endblock %} {% block page_sub %}
Lizenzstatus, Module und Aktivierung dieses Systems
{% endblock %}