Commit Graph

3339 Commits

Author SHA1 Message Date
Eduard Gert
b16bdf5e8f refetch restrictions on window visibility change 2026-06-16 13:30:17 +02:00
Eduard Gert
4ae37919c0 keep general settings tab visible when update settings are locked 2026-06-16 12:24:06 +02:00
Eduard Gert
951e08e35c add mdm helper (windows) (can be deleted later) 2026-06-16 12:11:47 +02:00
Eduard Gert
64c9551a4d remove "Loading..." from profile dropdown and show skeleton 2026-06-16 12:09:49 +02:00
Eduard Gert
44156b6256 mdm test script (can be deleted later) 2026-06-16 11:33:10 +02:00
Eduard Gert
ebaaddc14b show macos dock icon when any window is visible 2026-06-16 11:32:04 +02:00
Eduard Gert
28d85ecae3 adjust offset on macos 2026-06-15 16:27:44 +02:00
Eduard Gert
c37f24d1b0 adjust vertical offset on macos 2026-06-15 16:13:03 +02:00
Eduard Gert
c7a338c006 update config on config changed event 2026-06-15 16:13:03 +02:00
braginini
8f200e8489 Change browser login wording 2026-06-15 15:46:33 +02:00
Eduard Gert
780296a7db force disable spellcheck for inputs 2026-06-15 14:53:37 +02:00
Eduard Gert
91cbae8910 fix session expired dialog 2026-06-15 14:15:39 +02:00
Eduard Gert
4f72be6a42 fix mdm advanced view 2026-06-15 14:00:05 +02:00
Eduard Gert
83c9e5b0d1 fix allowserverssh mdm 2026-06-15 13:54:07 +02:00
Eduard Gert
47efdd839c Merge remote-tracking branch 'origin/ui-refactor' into ui-refactor 2026-06-15 13:20:34 +02:00
Eduard Gert
90be56788a fix mdm allowserverssh 2026-06-15 13:20:16 +02:00
Zoltán Papp
715a2b0943 docs(contributing): update UI build guidelines for Wails v3
The UI client migrated from Fyne to Wails v3 + React. Update the
Requirements and Build sections accordingly, fix the Windows installer
UI build command to use the task runner, bump the Go version to 1.25,
and drop the now-redundant client/ui/README.md.
2026-06-15 13:19:45 +02:00
Zoltán Papp
b6246e7c02 refactor(ui): extract critical severity into a constant
The critical-event gate compared against a bare "critical" literal while
the matching string is produced from the proto SystemEvent_CRITICAL enum in
systemEventFromProto. Add services.SeverityCritical next to the Status*
constants so the two sides share one definition.
2026-06-15 12:31:23 +02:00
Zoltán Papp
37eb150535 fix(ui): match severity gate case-insensitively
The critical-event gate used a case-sensitive == "critical" where every
other status/severity compare in the UI uses strings.EqualFold, so a
daemon-side reword to a different case would silently drop the bypass.
2026-06-15 12:29:50 +02:00
Zoltán Papp
6c15e8b51c fix(ui): close session bus when XEmbed host fails to start
newXembedHost failure left the private session bus open, leaking an fd
per RegisterStatusNotifierItem on systems without an XEmbed tray. Add a
closeBus helper that logs on close failure and use it at every back-off
path instead of discarding the error.
2026-06-15 12:27:46 +02:00
Zoltán Papp
b0f08645c3 fix(ui): install X11 error handler so tray races don't kill the UI
Xlib's default protocol-error handler calls exit() on any async X error,
so a tray race (tray manager window dying between find and dock, XMoveWindow
on a popup the WM already destroyed) would take the whole UI process down.

Install process-global logging no-op handlers via XSetErrorHandler/
XSetIOErrorHandler after every XOpenDisplay. Since the handler slot is
process-global and GDK init can clobber it, additionally wrap the popup
code's raw Xlib calls on GDK's Display in gdk_x11_display_error_trap_push/
pop_ignored, which is independent of the global handler.
2026-06-15 12:26:53 +02:00
Eduard Gert
2089b79630 show profiles also when mdm update setting is active 2026-06-15 12:20:28 +02:00
Zoltan Papp
c68bb8f99f fix(ui): resolve active profile before GetConfig in GetRestrictions
GetRestrictions called the daemon GetConfig with an empty
GetConfigRequest, which the daemon has rejected since multi-profile
support landed ("active profile name is empty") because it reads the
profile name from the request. Resolve the active profile via
GetActiveProfile first and pass its name/username, mirroring the
working Settings.GetConfig path. GetActiveProfile self-heals to the
default profile, so a valid name is always supplied; the
profile-switch-disabled MDM flag is orthogonal and unaffected.
2026-06-15 12:04:50 +02:00
Zoltan Papp
9e5bcb26eb fix(ui): include error name and message in forwarded logs
WebKit (macOS WKWebView) omits the "Name: message" header from
Error.stack, so forwarding only the stack hid the real cause of
failures. Prepend the error name, message and optional cause before
the stack so daemon RPC errors surface in gui-client.log.
2026-06-15 11:57:34 +02:00
Zoltan Papp
c9aed1a7c4 Merge branch 'main' into ui-refactor 2026-06-15 11:49:35 +02:00
Zoltan Papp
2959979f37 chore(ui): bump wails/v3 to v3.0.0-alpha.102 2026-06-15 11:44:44 +02:00
Zoltán Papp
7b08e750d5 feat(ui): hide macOS Dock icon, run as tray-only accessory app 2026-06-15 11:26:57 +02:00
Bethuel Mmbaga
cd777395f2 [management] Skip JWT group evaluation for embedded-IdP local users (#6422)
When JWT group sync is enabled with a restrictive JWTAllowGroups list, the local owner of an embedded-IdP (Dex) deployment can get locked out. The allow-groups check runs account-wide but local password users do not receive
external IdP group claims, so they can't satisfy the allowed list.

This skips JWT group evaluation for local Dex users so the restriction and JWT group sync continue to apply to external-IdP users as intended.
2026-06-15 12:01:54 +03:00
Eduard Gert
79e0a05f52 fix psk behaviour and allow to clear psk 2026-06-15 10:43:48 +02:00
Zoltan Papp
ec366163e3 ci(codespell): skip translated locale dirs and TRANSLATING.md
Non-English UI translations and the foreign-language examples in
TRANSLATING.md trip codespell on real foreign words. Extend the skip
list to cover es, fr, it, pt, ru, zh-CN locale dirs and the
TRANSLATING.md doc, keeping en/common.json as the source of truth.
2026-06-13 02:24:22 +02:00
Zoltan Papp
2d54c7f088 routeselector: remove duplicate IsDeselectAllActive
IsDeselectAllActive was identical to IsDeselectAll (both return the
deselectAll flag under a read lock). The two were introduced in parallel
on separate branches for the same fix - guarding against management route
sync overriding a user's explicit deselect-all - and ended up coexisting
after the branches merged.

Drop IsDeselectAllActive, keep the canonical IsDeselectAll from main, and
move its richer doc comment over. Update callers accordingly.
2026-06-13 00:50:42 +02:00
Zoltan Papp
a1a24bd777 Add in-body comment to startStatusNotifierWatcher no-op stub 2026-06-13 00:42:42 +02:00
Zoltan Papp
f0ac331fdc [client/server] fix connect retry test for PermissionDenied short-circuit
Commit 8841b950a made connectWithRetryRuns stop after a single login
attempt on PermissionDenied, but TestConnectWithRetryRuns still asserted
the loop retries 3+ times, so it failed with counter=1.

Repurpose the test (now TestConnectStopsRetryOnPermissionDenied) to
verify the loop stops after exactly one login on PermissionDenied,
keeping the fast retry env config that would otherwise drive several
attempts. Also redirect profile paths to a temp dir so it runs without
root.
2026-06-13 00:39:59 +02:00
Zoltan Papp
ae3f5b1088 Reorder UI service files to follow member-ordering convention
Group all type declarations at the top, keep each type's methods with it,
move package-level helpers and static functions to the end of the file.

- connection.go: ClientError methods sit directly under the struct; the
  classifyDaemonError / translateShort helpers move to the file end.
- windowmanager.go: the title / retitleAll / hideOtherWindowsLocked /
  restoreHiddenWindowsLocked / getScreenBasedOnCursorPosition helpers and the
  errorDialogURL / u32ptr static functions move to the file end; u32ptr no
  longer splits the const/var block.
2026-06-13 00:37:00 +02:00
Zoltan Papp
edf7e2d04d Tighten verbose comments in Wails UI Go code
Shorten over-long godoc/inline comments across the client/ui tray and
services code: drop narrative restatement, legacy-Fyne tangents, and text
already evident from signatures and names. Keep only the non-obvious why
(concurrency/lock ordering, platform quirks, ordering constraints, the
profile-switch state table). No code changes.
2026-06-13 00:22:27 +02:00
Eduard Gert
c2b43b9cf0 localize installer unknown-error fallback and abort debug bundle on unmount 2026-06-12 18:06:58 +02:00
Eduard Gert
8f2429c637 move debounced save out of SettingsContext setState updater 2026-06-12 18:06:38 +02:00
Eduard Gert
6cc6d68b37 add mdm 2026-06-12 18:00:28 +02:00
riccardom
c4d4208ea6 Template alignment 2026-06-12 16:13:23 +02:00
riccardom
aae6a924e2 Adds DisableAdvancedView optional MDM flag 2026-06-12 16:07:12 +02:00
Zoltán Papp
d3f62458d2 fix(ui): route tray status repaints through relayoutMenu to fix item races
buildMenu reassigns every menu item pointer under menuMu, but the status
path (refreshMenuItemsForStatus, applyStatusIndicator), the click handlers
and the session ticker read them unguarded. Wails dispatches event
listeners and OnClick callbacks on fresh goroutines, so these reads race
the rebuilds and applyStatus even runs concurrently with itself.

- applyStatus drives a single aggregated relayoutMenu (status, daemon
  version and session-deadline changes); refreshMenuItemsForStatus is
  removed — relayoutMenu repaints the same items from the caches
- applyStatusIndicator is SetBitmap-only: its unguarded SetMenu could
  reinstall a stale tree and pushed a half-built one on every relayout
- Connect/Disconnect handlers receive the clicked item from the buildMenu
  closure instead of reading the menuMu-guarded fields
- applySessionExpiry is cache-only; the row is painted by relayoutMenu,
  the 30s ticker snapshots its item under menuMu
- drop loadProfiles' dead unguarded profileSubmenu nil-check
2026-06-12 15:36:36 +02:00
Zoltán Papp
381532d166 Apply gofmt 2026-06-12 15:32:51 +02:00
Zoltan Papp
47ecc41bf4 Merge main into ui-refactor; port MDM support to the Wails UI
Integrates main's MDM configuration-profile feature and adapts it to the
Wails UI (this branch had already replaced the Fyne UI).

Conflict resolution:
- go.mod/go.sum: take main's deps; howett.net/plist pinned to v1.0.2-... (tidy)
- client/proto/daemon.pb.go: regenerated from the merged daemon.proto
- client/internal/peer/status.go: union of ipToKey (main) + sessionExpiresAt (HEAD)
- client/server/server.go: main's intent/liveness model (connectionGoroutineRunning,
  clientRunning no longer cleared by the goroutine) + empty-PSK guard
- client/ui/client_ui.go, client/ui/profile.go: removed (dead Fyne UI)

MDM port (backend + tray):
- services/settings.go: expose MDMManagedFields plus a managedFields map keyed
  by Config field names so the settings form can gate a control without
  translating mdm.Key* names
- tray: gate Profiles / Exit Node menus on DisableProfiles / DisableNetworks via
  GetFeatures, refreshed on the config_changed system event (replaces the legacy
  2s poll); localized MDM policy-applied toast in all shipped locales
- client/proto/metadata.go: shared constants for the config_changed /
  policy_applied event markers

PreSharedKey: GetConfig now returns preSharedKeySet (bool) instead of the masked
value; the settings form provides its own placeholder and sends a new key only
when the user types one.
2026-06-12 15:27:23 +02:00
Viktor Liu
b19467e3af [client] Answer NODATA when a host resolves without addresses of the requested family (#6418) 2026-06-12 14:50:46 +02:00
Riccardo Manfrin
2bcea9d582 [client] add MDM configuration profile support (Windows registry + macOS plist) (#6374)
* Initial scaffolding

* Applies MDM override

* Unit tests

* Helpers business logic

* Return error if trying to modify any config that is gated by MDM

* Add ManagedFields to returned config over GetConfig

* Adds initial 101 MDM policy business logic testing

* gRPC MDM changes

* MDM Name scoping for clarity

* Implements windows loading of MDM policy

* Adds missing WGPort config

* Cleanup setupKey to align to linear

* Align split tunnel code

* Adds some log

* Prefix every log with MDM

* Adds debug config cobra command

This can be useful for troubleshooting and checking config
now that its resolution is not trivial

defaults > config > env cars > CLI/UI > MDM

* Adds MDM 1m diff checker & reloader

* Adds also up/start after cancel

* Publishes event for UI to sync upon MDM changes

* Add events to resync UI to actual config

This also provide fixup for UI no aligning to changed config when coming from cli up with config flags.

* UI behavior conflicts relaxation

UI sends full config snapshot with all values. It doesn't
make sense to block it if the values are aligned with the
values constrained by the MDM policy. It's just simplier
to allow values that are compliant. (this goes for the CLI
as well at this point)

* Lock toggle Settngs

* Advanced Settings locking

* Fixup presharedkey

* Apply MDM locks

* Toggle gray in/out for Advanced Settings

* Adds support for disabling of Profiles and UpdateSettings feature flags

* Adds Gate Login as well when --disable-update-settings=true is given to service

This commit tries to settle things with an old PR-4237 which had relaxed
the case where the SetConfig returned an `Unavailable` code error.

Under this circumnstance the PR allowed the upFunc to just emit a warning and
progress further with the login gRPC. Since the login call is consuming
the --management-url coming from the `up` command, it might be possible
to abuse the "Unavailable" code to inject a management URL that is different
from the configured one even though the --disable-update-settings is set
to true (?)

* Evaluate disable-update-settings errors only when there's an actual override

* [UI] Fixup advanced Settings

* [UI] Fixup for preshared key

* [UI] Fixup for profile enable/disable toggle

We need to align the initial state to evaluate the delta in case.

The initial state has to be "true" since the profile starts visible.
Then we receive MDM and transition the cache bool value to the actual
MDM imposed state

* Enforces disable networks

* [UI] Aligns to "enable/disable once on change only"

* Fixup: MDM wins. always

* Removes --disable-advanced-settings

It was a typo in our meetings. the actual thing is --disable-update-settings

* [PROTO] Removes --disable-advanced-settings

* [UI] Removes --disable-advanced-settings

* Pins feat profile retrieval to notif event

* [UI] Fix for "hide" not working when propagating to parent with children

* Adds dep for reading plist files

* Introduces support for darwing plist loading

* Tests MDM config reload via ticker

* [PROVISIONING] ADMX/ADML/PS/bash scripts/templates

* CI fixes

- Add docstrings to `mdm_integration`
- refactor for cognitive complexity
- mod tidy

* Linting

* Add docstrings to `mdm_integration`

* nil,nil is no policy and no error. Allow it

* nil,nil is no policy and no error. Allow it

* exclude MDM profile adminstrated keys data from debug bundle

* Fixes Rosenpass left disable after MDM unlock

* Partial revert coderabbit added docstrings

* Renaming fix

* Avoid locking on clientRunning bool when the connection is aborted for whatever reason

We want to just signal this through the giveUpChan, we will manage the signal from
the waiter side and in case set it to false there. THis way we avoid locking,
which should allow the MDM down+wait_for_term_chan_signal_+up procedure

clientRunning is used to signal two different conditions here:

1. the initialization procedure is over (we have an engine)
2. the connection being up (or being attempted)

Probably these two functionalities should not alias, and the failure of the second condition
(because of any error) should just drive a reconnection (currently it's not happening,
and we silently go idle).
OR, mor probably, the two things are the SAME and there should not exist a case where
we did the "Up" initialization and connection attempt but we are not still attempting it.

* Moves test helper at te very bottom

* Addresses github comments

* No lock no copy

* Prevents engine not stopping within 10 secs from being paired by another instance

We instead juts SKIP updating the policy, so
1. the MDM ticker will kick in 1 minute time,
2. find the policy misaligned,
3. enter the onMDMPolicyChange,
4. find the s.clientRunning == true
   (because it is set to false only in server cleanupConnection,
   and not by s.actCancel())
5. call s.actCancel() again if not nil
6. immediately return from <-s.clientGiveUpChan
7. finally call s.restartEngineForMDMLocked()

* Since we ARE running there should be a config

If the config was cancelled midflight, connect will abort later on

* DisableAutoConnect should not stop a running connection.

DisableAutoConnect should just avoid the connection attempts *when the service starts*.
If we are started and we are up and running, DisableAutoConnect should not kick in.

Another PR will follow about this topic

* Removes unused vars

* Moves callback into Run method arg

* align comment to removal of DisableAutoConnect

DisableAutoConnect should just avoid the connection attempts *when the service starts*.
If we are started and we are up and running, DisableAutoConnect should not kick in

* Removes unused managed_fields data.

This was initially used to drive the UI but approach changed
to reload config/features upon notifications which makes this data redundant.

* Reorder stuff

* Unexport unrequired vars/functions

PoliciesEqual → policiesEqual
AllKeys → allKeys

* Adds list of MDM managed fields in the debug bundle
2026-06-12 12:28:49 +02:00
Eduard Gert
13174ed026 Merge remote-tracking branch 'origin/ui-refactor' into ui-refactor 2026-06-12 12:19:43 +02:00
Eduard Gert
29a165a586 bind saves to loaded profile to prevent cross-profile clobber 2026-06-12 12:19:30 +02:00
Zoltán Papp
71611f4a91 Remove temporary debug logs for notifyStateChange and state.Set 2026-06-12 12:15:27 +02:00
Eduard Gert
860be01ebe update debug bundle setting page 2026-06-12 12:09:10 +02:00
Maycon Santos
8ff3b06cf1 [client] Index peer tunnel IPs for faster PeerStateByIP lookup (#6412)
* [client] Index peer tunnel IPs for O(1) PeerStateByIP lookup

Replace the linear scan over all peers with an ipToKey map maintained
by AddPeer/RemovePeer, covering both IPv4 and IPv6 tunnel addresses.

Offline peers are intentionally no longer resolvable by IP: only active
peers can carry traffic, so IdentityForIP and the DNS disconnected-peer
filter now treat them as unknown, same as foreign IPs.

Skip the DNS answer filter for single-record responses; dropping the
only answer was always restored by the empty-answer escape hatch, so
the fast path is behavior-neutral.

* Ensure `ipToKey` entries are only removed if they match the peer being deleted, preventing accidental removal of unrelated mappings.
v0.72.4
2026-06-12 10:24:15 +02:00