Skip to content

Add firewall application along with other small improvements.#3353

Open
labre-rdc wants to merge 97 commits intoBornToBeRoot:mainfrom
labre-rdc:firewall-pr
Open

Add firewall application along with other small improvements.#3353
labre-rdc wants to merge 97 commits intoBornToBeRoot:mainfrom
labre-rdc:firewall-pr

Conversation

@labre-rdc
Copy link
Contributor

@labre-rdc labre-rdc commented Mar 2, 2026

Changes proposed in this pull request

  • Add firewall application.
  • Fix a few potential null dereferences in some validators and converters.
  • Add ValidationErrorTemplate for checkboxes.
  • Allow ValidationError to be clicked out of the way (restores on hovering/keyboard focus).
  • Fix ChildWindowStyle restricting the window size to 500 height instead of setting a default height.
  • Reuse existing validators in empty variants where applicable.
  • Make ListHelper.Modify generic. Avoid duplicates.
  • PowershellHelper: Support commands exceeding command line length limit.
  • NetworkInterfaceView: Fix all XAML warnings.
  • ProfileChildWindow: Always scale to 85% of main window width. Required for wider content.
  • Localized enum conversion (to/from int/string)
  • Fixed 2 warnings in ProfileView while being at it.

Related issue(s)

Copilot generated summary

Provide a Copilot generated summary of the changes in this pull request.

Copilot summary

{generated summary}

To-Do

  • Update documentation to reflect this changes
  • Update changelog to reflect this changes
  • Replace PR number placeholders in changelog.

Contributing

By submitting this pull request, I confirm the following:

labre-rdc added 21 commits March 2, 2026 12:58
…ratedRegex.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…o 500.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…Remove duplicates.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…f Int16.MaxValue by creating temporary scripts when necessary.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…ace.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…ences and for typed binding proxies.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…ties passed as parameter for null, empty strings or empty enumerables.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…anges.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
… simplify merge conflicts.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
@BornToBeRoot
Copy link
Owner

@labre-rdc thanks, i will review it when i have some time 😄

@labre-rdc
Copy link
Contributor Author

Sorry for the reference error. I’ll handle it tomorrow.

@BornToBeRoot
Copy link
Owner

No worries. I don't think I'll be able to review it until next week.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
@BornToBeRoot
Copy link
Owner

The default strings (English) must be added to “Strings.resx” (and “Strings.Designer.cs”). Transifex regularly checks for changes in this file in the repository. When changes are made, Transifex is updated and the new strings can be translated.
When a language is fully translated (or during a manual synchronization), Transifex sends a PR with the file Strings..resx, which is automatically validated by AppVeyor and then merged by Mergify.

I only commit these two files and discard the rest (Visual Studio automatically updates them with an empty string...).


But I restored it and pushed it to this branch, so you don't need to make any changes to the language 😄 I'll try to review the rest over the weekend. I think i will make some minor changes to the UI to align it with the other tools (like moving the buttons to the bottom so it will also resize correct)

@labre-rdc
Copy link
Contributor Author

The default strings (English) must be added to “Strings.resx” (and “Strings.Designer.cs”). Transifex regularly checks for changes in this file in the repository. When changes are made, Transifex is updated and the new strings can be translated. When a language is fully translated (or during a manual synchronization), Transifex sends a PR with the file Strings..resx, which is automatically validated by AppVeyor and then merged by Mergify.

I only commit these two files and discard the rest (Visual Studio automatically updates them with an empty string...).

I see. Well I considered it unreliable for testing, because the empty strings did apparently not fall back to the default culture for me in WPF (maybe I missed something), which means I was presented with empty buttons and headers when a non-English display language was used. For that reason I added the English translation and translated to German while being at it. This was also reasonable, because the UI elements would scale/wrap differently with other string lengths etc. As a side note, I think, you use Visual Studio in German language, because Strings.Designer.cs contains auto-generated german comments. This causes merge conflicts, when other contributors use IDEs in different languages.

But I restored it and pushed it to this branch, so you don't need to make any changes to the language 😄 I'll try to review the rest over the weekend. I think i will make some minor changes to the UI to align it with the other tools (like moving the buttons to the bottom so it will also resize correct)

Okay, fine for me, if you want to handle that. I might process a few of the Copilot review notes today or in the next few days.

labre-rdc and others added 22 commits March 13, 2026 12:07
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…by refactoring.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
…ion mapping in ProfileChildWindow.

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
@labre-rdc
Copy link
Contributor Author

Here is the Demo profile I used for the screenshots. Should you wish to do other style changes (maybe even after the merge), you can update the screenshots accordingly.

Demo.json

@BornToBeRoot
Copy link
Owner

BornToBeRoot commented Mar 17, 2026

Sorry—I just got around to writing this. Thanks again. I’ll update the screenshots and documentation as soon as this is implemented.

After reviewing the code and experimenting a bit with the firewall module, I noticed a few minor bugs:

  • If you switch between views (Firewall -> something else -> Firewall) and Firewall_LocalPortsHistoryConfig is null, a NullReferenceException occurs
  • In some cases, a profile’s firewall rules are overwritten (I think they aren’t passed as a value—but I don’t remember the steps to reproduce this)
  • The validation isn’t optimal either (editing a row in a DataGrid sometimes behaves strangely in WPF...). You can apply invalid rules, and the PowerShell command is then generated based on the input.

Anyway—before we spend time fixing this and reviewing the rest of the code, I’ve been thinking about tweaking the design a bit to make the behavior similar/consistent with the tools we already have (e.g., HostsFileEditor, ARP Table). Don't take this as criticism—I'm sure there were good reasons for implementing it this way in your project. I just want to keep the user experience consistent across all tools.

I think the HostsFileEditor is a good reference here:

  • The “Main” view should display the currently active rules (similar to the Hosts file editor, which shows what is currently in the Hosts file...). In the current behaviour you apply rules, then delete them (don't apply), restart NetworkManager, and the rules remain active but are no longer displayed in the view.
  • By adding/editing individual rules via a dialog, we could improve validation -> E.g. enable the OK button when validation passes / show a hint and message with the validation error (this is broken in DataGrid in WPF)
  • I think it should be possible to delete a single rule without affecting the others—currently, all rules are deleted and then reapplied (theoretically, all active connections are dropped—I haven’t tested this) -> maybe someone uses this to manage the rules on their web server and then this would affect users.
  • And i think we won't need a local history or the option to change the syntax... All other tools use ; to seperate ports - we can just "translate" them to the correct synatx we need for PowerShell... (this could also introduce other bugs -> a profile is saved with ; and then the syntax is changed... the PortRangeToPortSpecificationConverter will fail?)
  • EDIT 1:
    I think all rules can start with "NETworkManager - *" - if i look at the names in the Windows firewall settings, this should be fine. And you know directly who created it (without looking into the docs to see we use the NwM_ syntax...)

I’m not sure how to design a view for the profiles... but I would do that after reworking the main view / adding a dialog.

The idea in Paint -.-

image

I will start to work on this - You're welcome to help out if you'd like.

…istory settings correctly, e.g., call OnPropertyChanged().

Signed-off-by: Manuel Ullmann <manuel.ullmann@rediecon.com>
@labre-rdc
Copy link
Contributor Author

labre-rdc commented Mar 20, 2026

Fixed the null dereference, which could occur because the settings were not initialized and written properly. All references do null checks now. Also fixed the overall bogus behavior of the history erase. It could erase port entries, because the PropertyChanged chain would ultimately erase port configuration entries and a optimization in FirewallRuleGrid would prevent the entries to be refilled. Anyway, it should work now. The history size is now always checked, so the buttons reenable, when the history regains entries.

@labre
Copy link

labre commented Mar 20, 2026

Disregard the original reply to your comment. I’d like to rephrase and sum it up a bit.

So, all in all I understood the following points.

  1. A null dereference occurs related to the history.
  2. Profile firewall rules are overwritten.
  3. Invalid rules are applied.
  4. The rules applied in the Windows Firewall are not shown.
  5. The UX does not match the one of other applications.

So let me comment these one by one.

1. Null Dereference

While I could not reproduce it, I know why it happened for you. Thanks for pointing this out. I’ve fixed it as well as other issues related to the Erase history function. That was the last feature I developed and since it was related to well tested functionality I did not properly test it. Sorry for that, but it should work now and did go through proper testing.

2. Profile firewall rules are overwritten

I thought a lot about an intuitive interface design and came to the conclusion, that the selected profile should match the configuration shown in the main view (=rule list). That way there is never confusion about the currently loaded profile or whether the settings are stored. Thus the rules are immediately overwritten when a firewall rule is validly changed. Invalid changes never reach the model, so they are not stored. In other words, the behavior is intended.

3. Invalid rules are applied

That one is simple and I verified it in tests. I have rechecked the code and found the following line:

        return HasError && !toLoadOrSave ? null : _rule;

This is the ToRule() method in FirewallRuleViewModel. ToRule() is called by ApplyConfiguration() in the FirewallViewModel which is bound to the Apply button. HasError is bound to the visual style of the DataGridRow, which means, if it is red the rule is skipped. While documenting I thought I’d skip just specific rules, but actually any invalid configuration is skipped, even if the rule configuration never reaches the model. For that reason it is impossible, that invalid rules reach the PowerShell command. You must have misinterpreted something.

4. The rules applied in the Windows Firewall are not shown

Well, sorry about that, but this was not part of the project goals. I consider this a nice enhancement, but it is also non-trivial to find a non-confusing UI for that. For instance, how would we separate the Windows rules from the configuration rules? Do we show the Windows rules, no matter what configuration is loaded? Do we only show, whether the configured rules currently are applied? Do we need a separate view just for the Windows rules or do we combine both in one list? Again, this is non-trivial, however, creating a column with ToggleSwitches to allow applying individual rules and checking, whether they are already active would be feasible. However I would recommend against an implementation before the general merge. After all you already want to translate the whole module yourself, and the other translators also have some work to do. I still offer to do the German translation, but you denied my request in Transifex.

5. The UX does not match the one of other applications

I am aware of that. However, I have not seen collection based configurations in the other applications, so having another UX concept for this interface element class is fine in my personal opinion. Enhancements can be considered, like having a visual feedback for configuration changes and adding a save button to save them. Also a dialog asking for saving could be considered in that case. On the other hand, an undo function could make that obsolete. My goal was to keep it simple (KISS) which is actually a pattern to favor in terms UI design principles. I’ve actually learned that, although I never finished studying.

Other possibilities for collection based configurations (configurable DataGrids) are:

  • Routes
  • IPv4 addresses (not profile compatible currently as far as I have seen)
  • IPv6 addresses
  • Network interface configurations

As a final note, I want to point out, that I can not work any longer on that at work. Besides to having invested roughly 220 hours into it as opposed to 80 hours planned, which no company would normally invest without revenue, I also loose employment as of April. So don’t be surprised when the account gets deleted. I can provide bug fixes for anything you find, but I really would recommend to not rework this at this point. This is well tested and to my knowledge working code. If you find anything (with steps to reproduce), say something. I’m willing to maintain my code, but if you rewrite most of it, I’m less motivated. The documentation does currently not point out, that invalid rules are always skipped. That is the only missing part I can think of.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[New App] Firewall module/application

4 participants