Files
RouterOS/RouterOSAssistant/Features/Wizard/Steps/Setup/FirewallStepView.swift
T
KayandClaude Sonnet 5 c9ecd3a0a9 M9/M10: Einfach/Experte-Modus + Experte-Tab (generischer RouterOS-Zugriff)
M9: Einrichten-Wizard bekommt einen Einfach/Experte-Modusschalter
(ModeStepView). Einfach überspringt VLAN, erlaubt nur ein LAN-Netzwerk
ohne Isolation, Firewall-Grundschutz fest an.

M10: neuer "Experte"-Tab mit generischem Motor (RouterOSMenuItem,
RouterOSCommand.remove, ConnectionService.fetchMenuItems, freies
"eigener Menüpfad"-Feld) plus kuratierten Formularen mit Tooltips
(RouterOSSchemaCatalog) für Firewall/NAT/Mangle/Raw/Adress-Listen,
Interfaces, IP, VPN, WLAN, Queues, System, Werkzeuge.

Live gegen einen hEX-Testrouter verifiziert (erst per SSH, dann vom
Nutzer selbst in der App), dabei 7 reale Bugs gefunden und gefixt —
der wichtigste: RouterOS' SSH-CLI gibt bei fehlgeschlagenen Befehlen
Exit-Code 0 zurück, wodurch apply() app-weit Fehler verschluckte statt
sie zu melden. Danach ergänzt: Bestätigungsdialog vor Anlegen/Ändern
+ Auto-Backup vor dem ersten Experte-Tab-Schreibvorgang je Sitzung
(Angleichung an den Wizard), sowie ein Dauer-Editor (Tage/Std/Min/Sek)
für Lease-/Ablaufzeit-Felder statt Freitext.

Details zu allen Bugs/Fixes: HANDOFF.md, CHATLOG.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EW3r6rW1xCf6UT5jNvt6rn
2026-09-14 00:03:50 +02:00

80 lines
3.6 KiB
Swift

import SwiftUI
struct FirewallStepView: View {
@ObservedObject var viewModel: SetupViewModel
var body: some View {
Form {
Section {
if viewModel.mode == .expert {
Toggle(
"Firewall-Grundschutz einrichten (empfohlen)",
isOn: Binding(
get: { viewModel.firewallSectionEnabled },
set: { viewModel.setFirewallSectionEnabled($0) }
)
)
.help("Schützt deinen Router und deine Geräte vor unaufgeforderten Zugriffen aus dem Internet und ermöglicht deinen Geräten den Internetzugriff (NAT).")
} else {
Text("Firewall-Grundschutz ist im einfachen Modus immer aktiv.")
}
Text(
"Richtet einen Standard-Schutz ein: Internetfreigabe (NAT) für dein Heimnetz, "
+ "und blockiert unaufgeforderte Zugriffe aus dem Internet auf deinen Router "
+ "und deine Geräte. Bestehende, selbst eingerichtete Regeln bleiben erhalten — "
+ "die neuen Regeln werden vorangestellt."
)
.font(.caption)
.foregroundStyle(.secondary)
}
if viewModel.firewallSectionEnabled {
Section("Bereits vorhandene Regeln") {
if viewModel.isLoadingFirewallRuleCounts {
ProgressView()
} else if let counts = viewModel.existingFirewallRuleCounts {
LabeledContent("Filter-Regeln", value: "\(counts.filterRuleCount)")
LabeledContent("NAT-Regeln", value: "\(counts.natRuleCount)")
if counts.filterRuleCount > 0 || counts.natRuleCount > 0 {
Text(
"Dein Router hat bereits eigene Firewall-Regeln. Die neuen Regeln werden "
+ "vorangestellt, bestehende bleiben erhalten — prüfe nach dem Anwenden "
+ "trotzdem die Reihenfolge, z.B. über Winbox oder "
+ "\"/ip firewall filter print\"."
)
.font(.caption)
.foregroundStyle(.orange)
}
} else if let error = viewModel.firewallRuleCountsError {
Text(error).font(.caption).foregroundStyle(.red)
}
}
}
if !viewModel.isolatedNetworkNames.isEmpty {
Section("Isolierte Netzwerke") {
Text(viewModel.isolatedNetworkNames.joined(separator: ", "))
Text("Diese Netzwerke werden vom Datenverkehr aller anderen konfigurierten Netzwerke abgeschottet, sobald der Firewall-Grundschutz aktiv ist.")
.font(.caption)
.foregroundStyle(.secondary)
}
}
Section {
HStack {
Button("Zurück") { viewModel.goBack() }
Spacer()
Button("Weiter") { viewModel.goNext() }
}
}
}
.formStyle(.grouped)
.navigationTitle("Firewall (optional)")
.onAppear {
if viewModel.firewallSectionEnabled {
viewModel.loadExistingFirewallRuleCounts()
}
}
}
}