Commit Graph

2940 Commits

Author SHA1 Message Date
Eduard Gert
439f44c6b4 merge 2026-05-11 15:16:41 +02:00
Eduard Gert
b5a970155b Merge branch 'ui-refactor' into ui-refactor-ui 2026-05-11 15:15:11 +02:00
Eduard Gert
686e0d97f2 update Assets.car 2026-05-11 14:51:05 +02:00
Eduard Gert
0c287b6f4d fix vite dev server 2026-05-11 14:48:37 +02:00
Eduard Gert
f7f5946910 update components 2026-05-11 14:26:10 +02:00
Zoltan Papp
7a9f5a734f Merge branch 'main' into ui-refactor
Port IPv6 overlay support (#5631) into the Wails UI:
- Add DisableIPv6 config toggle to Settings (NetworkTab + services)
- Filter ::/0 alongside 0.0.0.0/0 as an exit-node route
- Suppress duplicate v6 default-route notifications in tray
2026-05-11 14:10:12 +02:00
Eduard Gert
1aae067aaa add settings skeleton 2026-05-11 13:58:41 +02:00
Zoltan Papp
28a7eba756 [client/ui] Remove unused xembed_host_other.go stub 2026-05-11 13:54:17 +02:00
Zoltan Papp
8841b950a2 [client/server] Stop retry loop after PermissionDenied login
Without marking the error as backoff.Permanent the outer retry re-enters
connect(), which resets the daemon state from NeedsLogin to Connecting
and makes the tray flicker between the two until the user logs in.
2026-05-11 13:43:53 +02:00
Eduard Gert
0c2702c0d7 update height and wording 2026-05-11 13:30:05 +02:00
Zoltan Papp
b43a09a1c7 [client/ui] Add tray icon for needs-login/login-failed states
The tray now switches to a dedicated lock icon when the daemon reports
NeedsLogin, SessionExpired or LoginFailed — the latter mirrors the CLI,
which groups these three statuses together as "needs authentication"
and prints the same "Run netbird up" prompt. The macOS template variant
reuses the existing error-macos PNG because the project's macOS tray
PNGs use a 2-color (black + transparent) convention that rsvg-convert
of the badge-style SVG sources can't reproduce. The earlier badge-style
SVG sketches in assets/svg/ are removed (they were marked as reference
only and never matched the shipping PNG design).
2026-05-11 13:22:30 +02:00
Zoltan Papp
595dfbb6f1 [client/ui] Distinguish "daemon not running" tray state
The status stream emits a synthetic StatusDaemonUnavailable when the
gRPC client or stream cannot be established, fired once per outage and
cleared on the next real snapshot. The tray maps it to a "Not running"
status label, switches the icon to the error variant, hides
Connect/Disconnect (neither would work without the daemon), and
disables Settings, Networks and Create Debug Bundle so the user is not
routed to pages that would just fail to load.
2026-05-11 12:22:47 +02:00
Zoltan Papp
7f560df9be [client/ui] Tray menu opens on click; hide window at startup
Left-click on the tray icon now opens the menu on every platform — the
window is reached through a new "Open NetBird" entry. Only the action
that matches the current daemon state is shown: Connect when
disconnected, Disconnect when connected. The main window starts hidden
and is only surfaced via the tray, single-instance launch, or daemon
events.
2026-05-11 12:01:46 +02:00
Zoltán Papp
09052949a2 [client/ui] Finish ui-wails rename (import paths, fyne deps)
Follow-up to the rename commit: the previous commit moved the files but
the post-mv string substitutions (Go imports, frontend bindings, CI
config paths) were not re-staged so they slipped through. This commit
applies those edits and removes the fyne dependencies from go.mod/go.sum
now that the legacy fyne UI is gone.
2026-05-11 11:33:35 +02:00
Zoltán Papp
9aef31ff53 [client/ui] Replace fyne UI with Wails (rename ui-wails to ui)
Removes the legacy fyne-based client/ui implementation and renames the
Wails replacement (client/ui-wails) to take its place at client/ui. Go
imports, frontend bindings, CI workflows, goreleaser configs and the
windows .syso icon path are updated to follow the rename.
2026-05-11 11:20:22 +02:00
Zoltán Papp
08f52f4517 [client/server] Allow clearing pre-shared key via SetConfig
The daemon ignored an empty OptionalPreSharedKey, so a UI/CLI request to
clear the pre-shared key was silently dropped. Pass the pointer through
unconditionally — profilemanager already handles the empty-string case.
2026-05-11 11:02:39 +02:00
Viktor Liu
a4114a5e45 [client] Skip DNS upstream failover on definitive EDE (#6089) 2026-05-11 10:00:23 +02:00
Viktor Liu
6b08e89c7b [relay] Preserve non-standard port in WS dialer URL prep (#6061) 2026-05-11 09:59:33 +02:00
Viktor Liu
a852b3bd34 [client, proxy] Harden uspfilter conntrack and share TCP relay (#5936) 2026-05-11 09:59:13 +02:00
Viktor Liu
afb83b3049 [client] Use unique temp file and clean up on failure when writing ssh config (#6064) 2026-05-11 09:58:49 +02:00
Eduard Gert
18e3b5dd32 fix about 2026-05-11 09:37:14 +02:00
Eduard Gert
f3f9704c6f update about 2026-05-08 17:55:41 +02:00
Eduard Gert
4c3d4effbd update troubleshooting 2026-05-08 17:18:25 +02:00
Nicolas Frati
e89aad09f5 [management] Enable MFA for local users (#5804)
* wip: totp for local users

* fix providers not getting populated

* polished UI and fix post_login_redirect_uri

* fix: make sure logout is only prompted from oidc flow

Signed-off-by: jnfrati <nicofrati@gmail.com>

* update templates

Signed-off-by: jnfrati <nicofrati@gmail.com>

* deps: update dex dependency

Signed-off-by: jnfrati <nicofrati@gmail.com>

* fix qube issues

Signed-off-by: jnfrati <nicofrati@gmail.com>

* replace window with globalThis on home html

Signed-off-by: jnfrati <nicofrati@gmail.com>

* fixed coderabbit comments

Signed-off-by: jnfrati <nicofrati@gmail.com>

* debug

* remove unused config and rename totp issuer

* deps: update dex reference to latest

* add dashboard post logout redirect uri to embedded config

* implemented api for mfa configuration

* update docs and config parsing

* catch error on idp manager init mfa

* fix tests

* Add remember me  for MFA

* Add cookie encryption and session share between tabs

* fixed logout showing non actionable error and session cookie encription key

* fixed missing mfa settings on sql query for account

* fix code index for mfa activity

---------

Signed-off-by: jnfrati <nicofrati@gmail.com>
Co-authored-by: braginini <bangvalo@gmail.com>
2026-05-08 16:31:20 +02:00
Eduard Gert
3953fee5a4 update ssh and advanced settings tabs 2026-05-08 10:57:31 +02:00
Eduard Gert
adeaa49cda update switch 2026-05-07 17:27:56 +02:00
Eduard Gert
2c5d52a1bf update wording 2026-05-07 17:19:56 +02:00
Eduard Gert
70a755fbae add general settings 2026-05-07 16:47:52 +02:00
Maycon Santos
7da94a4956 [misc] Update CONTRIBUTING.md (#6076) 2026-05-07 16:16:48 +02:00
Pascal Fischer
39eac377e4 [management] add update reason to buffered calls (#6103) 2026-05-07 15:55:59 +02:00
Eduard Gert
559da5d5b9 refactor 2026-05-07 15:00:36 +02:00
Eduard Gert
614ee11ac7 update CFBundleDisplayName 2026-05-07 14:19:34 +02:00
Eduard Gert
85080afa59 use new mac style icons 2026-05-07 14:14:26 +02:00
Zoltán Papp
a5cc8da054 [client] Pre-seed CustomActivator CLSID under HKCU AppUserModelId\NetBird
The Wails notifications service reads HKCU\Software\Classes\AppUserModelId\
<AppName>\CustomActivator on first startup; if present it uses that GUID
as the toast activator CLSID, otherwise it generates a fresh UUID and
writes it back. Without an installer-supplied value the per-machine GUID
diverges from the ToastActivatorCLSID baked into the Start Menu and
Desktop shortcuts, and the COM activator never fires when a toast is
clicked. Seed the same CLSID the shortcuts use so the two sides match.
2026-05-07 13:00:51 +02:00
Zoltán Papp
a4fd5a78b4 [client/ui-wails] Set application Name to "NetBird" for Windows toasts
Windows uses application.Options.Name as the toast AppUserModelID and as
the registry path the Wails notifier reads/writes its CustomActivator
under (HKCU\Software\Classes\AppUserModelId\<Name>). The MSI installer
seeds those under "NetBird"; with the previous "netbird-ui" Name the app
would have written under a different identity and the toast activator
CLSID the installer pre-registers would have been orphaned.
2026-05-07 12:59:01 +02:00
Eduard Gert
062a183e4e update settings nav 2026-05-07 12:40:04 +02:00
Viktor Liu
205ebcfda2 [management, client] Add IPv6 overlay support (#5631) 2026-05-07 11:33:37 +02:00
Eduard Gert
a2be41caf8 add about setting 2026-05-07 11:24:11 +02:00
Zoltán Papp
5b70989e3e [client/ui-wails] Make /update page faithful to the legacy auto-update dialog
Adds the missing info line ("Your client version is older than the
auto-update version set in Management. Updating client to: <version>.")
and replaces the spinner with the legacy 1-second dot animation
(Updating./.../...). Terminal-state wording now matches the Fyne UI
exactly: 15 min timeout, canceled, and "Update failed: <err>".

Ports mapInstallError from client/ui/update.go so daemon errors that
embed "deadline exceeded" / "canceled" hit the right branch instead of
falling through as a generic failure.

Detects the daemon dropping mid-upgrade (the legacy success signal):
if GetInstallerResult fails for 5s straight, call the new Update.Quit
service method to exit, mirroring app.Quit() in showInstallerResult.
2026-05-07 10:35:18 +02:00
Zoltán Papp
d324a5ff48 [ci] Stub frontend/dist before lint so the Wails embed pattern matches
client/ui-wails/main.go embeds all:frontend/dist, which is produced by
the frontend build and gitignored. Lint runs don't build the frontend,
so the directory is missing in CI and golangci-lint fails the typecheck.
Create a placeholder file before linting so the embed has something to
match.
2026-05-07 10:23:02 +02:00
Eduard Gert
debb558aa3 wip 2026-05-07 09:57:14 +02:00
Zoltán Papp
cce80f8276 [client/ui-wails] Drop dead freebsd branches in services/connection.go
The file's build constraint excludes freebsd, so the freebsd cases in
IsUnixDesktopClient and OpenURL were unreachable — staticcheck (SA4032)
fails the pre-push lint. Linux is the only Unix-desktop GOOS this
package compiles for, so collapse both checks accordingly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 18:00:51 +02:00
Zoltán Papp
05ee4e52b8 [client/ui-wails] Make the SSO login flow recoverable from a stuck state
A pending WaitSSOLogin parks the daemon on an OAuth UserCode forever
once the user closes the browser without completing the flow. The
frontend can't unblock that on its own — it needs the daemon to fire
its own actCancel(). Three fixes work together:

- Login() now issues a Down() before kicking off the new flow so a
  previously-stuck WaitSSOLogin is unwedged before we ask the daemon
  for fresh OAuth info.
- The Login page's Cancel button calls Down() before navigating away,
  so abandoning the flow mid-browser actually settles the daemon's
  in-flight WaitSSOLogin instead of leaving it pinned.
- Status keeps the Login button visible whenever we aren't Connected
  (including Connecting), so a UI restart that finds the daemon stuck
  in Connecting still has a one-click recovery path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:59:50 +02:00
Zoltán Papp
bb2bf673a0 [client/ui-wails] Wire up the SSO login flow end-to-end
Mirror the Fyne client's login path: the daemon Login RPC now defaults
ProfileName/Username from GetActiveProfile + the OS user and sets
IsUnixDesktopClient on Linux/FreeBSD so the daemon picks the SSO
browser flow. A new OpenURL service launches the user's default
browser via xdg-open / open / rundll32 (Fyne's openURL helper) — the
embedded WebKit's window.open silently fails for external URLs.

The frontend gains a Login page that drives the full Login →
window.open via OpenURL → WaitSSOLogin → Up sequence with progress
states. Status surfaces a Login button while the daemon reports
NeedsLogin/SessionExpired, and the tray's status row stops being a
purely-decorative label: it becomes a clickable Login entry whenever
re-authentication is required.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:48:47 +02:00
Zoltán Papp
91c745e5e8 [client/ui-wails] Tear down the whole tray popup tree on focus loss
Replace the per-submenu focus-out handler with a shared idle-deferred
recheck: when any popup loses focus, ask after the next event-loop
turn whether *any* of our popups still owns toplevel focus. If none
does, the user clicked outside the menu tree, so close every popup at
once instead of leaking the parent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:19:55 +02:00
Zoltán Papp
68c38247f1 [client/ui-wails] Add submenu support to the XEmbed tray popup
Recursively walk dbusmenu children-display="submenu" entries when
flattening the SNI menu so the GTK popup can render nested items.
The C side renders submenu folders as labeled buttons that open a
child popup window aligned to the anchor row, kept on-screen with
horizontal flipping; the top-level popup no longer self-destructs
when focus transfers to one of its own submenus.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:17:54 +02:00
Zoltan Papp
f23aaa9ae7 [client] iOS: structured ResolvedIPs collection for domain routes (#6090)
* [client] iOS: structured ResolvedIPs collection for domain routes

Replace comma-joined ResolvedIPs string with a gomobile-friendly
ResolvedIPs collection (Add/Get/Size), mirroring the Android bridge
in client/android/network_domains.go.

This allows the iOS app to match domain-route resolved IPs against
connected peer routes without parsing CSV strings, fixing the route
status indicator for dynamic (DNS) routes.

* [client] iOS: align dynamic route exposure with Android bridge

For dynamic (DNS) routes the Swift side previously received
"invalid Prefix" as the Network value, forcing UI code to special-case
that sentinel. The Android bridge uses Domains.SafeString() instead so
peer.routes entries (which also derive from Domains.SafeString()) match
directly. Mirror that here.

Also fix the resolved IP lookup: resolvedDomains is keyed by the
resolved domain (e.g. api.ipify.org), not the configured pattern
(e.g. *.ipify.org). Group entries by ParentDomain like the daemon does
in client/server/network.go, so wildcard route patterns get their
resolved IPs populated.
2026-05-06 17:14:11 +02:00
Zoltán Papp
8b8f38de1b [client/ui-wails] Show GUI and daemon versions in the About submenu
Restore the legacy Fyne UI's two disabled "GUI: x.y.z" / "Daemon: a.b.c"
entries under About so users (and support) can read the running
versions from the tray. The GUI line is baked in at build time via
version.NetbirdVersion() — the same -ldflags chain the rest of the
repo uses. The daemon line starts as "—" and is rewritten in
applyStatus on every Status snapshot whose DaemonVersion differs from
the last one we recorded, so a daemon restart with a new build
(e.g. after an enforced update) updates the menu automatically.

Drive-by: rename the local variable that shadowed the version package
in handleUpdate so the import resolves cleanly.
2026-05-06 16:55:52 +02:00
Zoltán Papp
2b272e74c8 [client/ui-wails] In-process StatusNotifierWatcher + XEmbed tray bridge
Wails3's Linux systray hands the icon off to whatever process owns
org.kde.StatusNotifierWatcher on the session bus. Bare WMs (Fluxbox,
OpenBox, i3, dwm, sway, vanilla GNOME without the AppIndicator
extension) ship no watcher, so the icon registration silently fails
and the tray never appears — leaving a tray-only app like NetBird
unreachable.

Add a Linux-only watcher fallback that claims the watcher name when
nobody else does, plus an XEmbed bridge so legacy X11 system trays
(_NET_SYSTEM_TRAY_S0) can still render the icon. Both no-op on other
platforms via build tags.

Pieces:
- tray_watcher_linux.go: claims org.kde.StatusNotifierWatcher on a
  private session bus, exports the bare RegisterStatusNotifierItem /
  RegisterStatusNotifierHost surface, and spins up an XEmbed host per
  registered SNI item.
- xembed_host_linux.go: per-item event loop. Polls X11 events with a
  50ms ticker, listens for the SNI NewIcon signal, dispatches Activate
  / context menu through dbusmenu (com.canonical.dbusmenu).
- xembed_tray_linux.{c,h}: the X11/cairo native bits. Window is created
  with CopyFromParent visual + ParentRelative background so transparent
  pixels show the toolbar beneath instead of solid black on 24-bit
  trays. cairo paints the IconPixmap with OVER blending so per-pixel
  alpha is honoured against the parent-relative base. GTK3 owns the
  context-menu popup; menu items round-trip through dbusmenu Event.
- tray_linux.go: forces WEBKIT_DISABLE_DMABUF_RENDERER=1 in init() so
  developers running `task dev` / launching the binary directly get the
  same software rendering path the .desktop launcher already enables;
  the deb/rpm Exec wrapper covers installed users.
- tray_watcher_other.go and xembed_host_other.go: build-tag stubs so
  main.go's startStatusNotifierWatcher() compiles on every platform.
- main.go: calls startStatusNotifierWatcher() before NewTray so the
  Wails systray's RegisterStatusNotifierItem call hits a watcher we
  control on bare WMs.
- build/linux/netbird-ui.desktop: regenerated by `task build` to wrap
  the dev launcher's Exec line with the WEBKIT_DISABLE_DMABUF_RENDERER
  env, matching what the tray_linux.go init does at runtime.

Adapted from work originally prototyped on the prototype/ui-wails branch.

Tested on Fluxbox (Debian 13): the icon appears in the slit/toolbar with
the toolbar's background showing through transparent pixels, left-click
opens the window, right-click brings up the GTK popup of the dbusmenu
items.
2026-05-06 16:47:35 +02:00
Zoltán Papp
e6cbf30415 [client/ui-wails] Surface daemon SessionExpired in the tray
Port the Fyne UI's onSessionExpire 1:1 to the Wails tray so an SSO token
expiry no longer leaves the user staring at a stale peer list. When
applyStatus sees the transition into the daemon's StatusSessionExpired,
fire a single OS notification (the lastStatus guard rate-limits it to
the transition itself, mirroring the Fyne sendNotification flag) and
bring the main window forward on the /login route so the frontend can
drive the renewed SSO flow. The Fyne client achieved the same end with
a runSelfCommand "login-url" helper; here the window is already
in-process so we route to it directly.
2026-05-06 15:57:34 +02:00