mirror of
https://github.com/netbirdio/netbird.git
synced 2025-08-17 10:31:45 +02:00
[client] Feat: Support Multiple Profiles (#3980)
[client] Feat: Support Multiple Profiles (#3980)
This commit is contained in:
@ -8,8 +8,10 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@ -34,11 +36,14 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface"
|
||||
"github.com/netbirdio/netbird/client/internal"
|
||||
"github.com/netbirdio/netbird/client/internal/profilemanager"
|
||||
"github.com/netbirdio/netbird/client/proto"
|
||||
"github.com/netbirdio/netbird/client/ui/desktop"
|
||||
"github.com/netbirdio/netbird/client/ui/event"
|
||||
"github.com/netbirdio/netbird/client/ui/process"
|
||||
|
||||
"github.com/netbirdio/netbird/util"
|
||||
|
||||
"github.com/netbirdio/netbird/version"
|
||||
@ -54,11 +59,11 @@ const (
|
||||
)
|
||||
|
||||
func main() {
|
||||
daemonAddr, showSettings, showNetworks, showLoginURL, showDebug, errorMsg, saveLogsInFile := parseFlags()
|
||||
flags := parseFlags()
|
||||
|
||||
// Initialize file logging if needed.
|
||||
var logFile string
|
||||
if saveLogsInFile {
|
||||
if flags.saveLogsInFile {
|
||||
file, err := initLogFile()
|
||||
if err != nil {
|
||||
log.Errorf("error while initializing log: %v", err)
|
||||
@ -74,19 +79,28 @@ func main() {
|
||||
a.SetIcon(fyne.NewStaticResource("netbird", iconDisconnected))
|
||||
|
||||
// Show error message window if needed.
|
||||
if errorMsg != "" {
|
||||
showErrorMessage(errorMsg)
|
||||
if flags.errorMsg != "" {
|
||||
showErrorMessage(flags.errorMsg)
|
||||
return
|
||||
}
|
||||
|
||||
// Create the service client (this also builds the settings or networks UI if requested).
|
||||
client := newServiceClient(daemonAddr, logFile, a, showSettings, showNetworks, showLoginURL, showDebug)
|
||||
client := newServiceClient(&newServiceClientArgs{
|
||||
addr: flags.daemonAddr,
|
||||
logFile: logFile,
|
||||
app: a,
|
||||
showSettings: flags.showSettings,
|
||||
showNetworks: flags.showNetworks,
|
||||
showLoginURL: flags.showLoginURL,
|
||||
showDebug: flags.showDebug,
|
||||
showProfiles: flags.showProfiles,
|
||||
})
|
||||
|
||||
// Watch for theme/settings changes to update the icon.
|
||||
go watchSettingsChanges(a, client)
|
||||
|
||||
// Run in window mode if any UI flag was set.
|
||||
if showSettings || showNetworks || showDebug || showLoginURL {
|
||||
if flags.showSettings || flags.showNetworks || flags.showDebug || flags.showLoginURL || flags.showProfiles {
|
||||
a.Run()
|
||||
return
|
||||
}
|
||||
@ -106,21 +120,35 @@ func main() {
|
||||
systray.Run(client.onTrayReady, client.onTrayExit)
|
||||
}
|
||||
|
||||
type cliFlags struct {
|
||||
daemonAddr string
|
||||
showSettings bool
|
||||
showNetworks bool
|
||||
showProfiles bool
|
||||
showDebug bool
|
||||
showLoginURL bool
|
||||
errorMsg string
|
||||
saveLogsInFile bool
|
||||
}
|
||||
|
||||
// parseFlags reads and returns all needed command-line flags.
|
||||
func parseFlags() (daemonAddr string, showSettings, showNetworks, showLoginURL, showDebug bool, errorMsg string, saveLogsInFile bool) {
|
||||
func parseFlags() *cliFlags {
|
||||
var flags cliFlags
|
||||
|
||||
defaultDaemonAddr := "unix:///var/run/netbird.sock"
|
||||
if runtime.GOOS == "windows" {
|
||||
defaultDaemonAddr = "tcp://127.0.0.1:41731"
|
||||
}
|
||||
flag.StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]")
|
||||
flag.BoolVar(&showSettings, "settings", false, "run settings window")
|
||||
flag.BoolVar(&showNetworks, "networks", false, "run networks window")
|
||||
flag.BoolVar(&showLoginURL, "login-url", false, "show login URL in a popup window")
|
||||
flag.BoolVar(&showDebug, "debug", false, "run debug window")
|
||||
flag.StringVar(&errorMsg, "error-msg", "", "displays an error message window")
|
||||
flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", os.TempDir()))
|
||||
flag.StringVar(&flags.daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]")
|
||||
flag.BoolVar(&flags.showSettings, "settings", false, "run settings window")
|
||||
flag.BoolVar(&flags.showNetworks, "networks", false, "run networks window")
|
||||
flag.BoolVar(&flags.showProfiles, "profiles", false, "run profiles window")
|
||||
flag.BoolVar(&flags.showDebug, "debug", false, "run debug window")
|
||||
flag.StringVar(&flags.errorMsg, "error-msg", "", "displays an error message window")
|
||||
flag.BoolVar(&flags.saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", os.TempDir()))
|
||||
flag.BoolVar(&flags.showLoginURL, "login-url", false, "show login URL in a popup window")
|
||||
flag.Parse()
|
||||
return
|
||||
return &flags
|
||||
}
|
||||
|
||||
// initLogFile initializes logging into a file.
|
||||
@ -168,6 +196,12 @@ var iconConnectingMacOS []byte
|
||||
//go:embed assets/netbird-systemtray-error-macos.png
|
||||
var iconErrorMacOS []byte
|
||||
|
||||
//go:embed assets/connected.png
|
||||
var iconConnectedDot []byte
|
||||
|
||||
//go:embed assets/disconnected.png
|
||||
var iconDisconnectedDot []byte
|
||||
|
||||
type serviceClient struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
@ -176,9 +210,13 @@ type serviceClient struct {
|
||||
|
||||
eventHandler *eventHandler
|
||||
|
||||
profileManager *profilemanager.ProfileManager
|
||||
|
||||
icAbout []byte
|
||||
icConnected []byte
|
||||
icConnectedDot []byte
|
||||
icDisconnected []byte
|
||||
icDisconnectedDot []byte
|
||||
icUpdateConnected []byte
|
||||
icUpdateDisconnected []byte
|
||||
icConnecting []byte
|
||||
@ -189,6 +227,7 @@ type serviceClient struct {
|
||||
mUp *systray.MenuItem
|
||||
mDown *systray.MenuItem
|
||||
mSettings *systray.MenuItem
|
||||
mProfile *profileMenu
|
||||
mAbout *systray.MenuItem
|
||||
mGitHub *systray.MenuItem
|
||||
mVersionUI *systray.MenuItem
|
||||
@ -214,7 +253,6 @@ type serviceClient struct {
|
||||
|
||||
// input elements for settings form
|
||||
iMngURL *widget.Entry
|
||||
iConfigFile *widget.Entry
|
||||
iLogFile *widget.Entry
|
||||
iPreSharedKey *widget.Entry
|
||||
iInterfaceName *widget.Entry
|
||||
@ -247,6 +285,7 @@ type serviceClient struct {
|
||||
isUpdateIconActive bool
|
||||
showNetworks bool
|
||||
wNetworks fyne.Window
|
||||
wProfiles fyne.Window
|
||||
|
||||
eventManager *event.Manager
|
||||
|
||||
@ -263,36 +302,50 @@ type menuHandler struct {
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
type newServiceClientArgs struct {
|
||||
addr string
|
||||
logFile string
|
||||
app fyne.App
|
||||
showSettings bool
|
||||
showNetworks bool
|
||||
showDebug bool
|
||||
showLoginURL bool
|
||||
showProfiles bool
|
||||
}
|
||||
|
||||
// newServiceClient instance constructor
|
||||
//
|
||||
// This constructor also builds the UI elements for the settings window.
|
||||
func newServiceClient(addr string, logFile string, a fyne.App, showSettings bool, showNetworks bool, showLoginURL bool, showDebug bool) *serviceClient {
|
||||
func newServiceClient(args *newServiceClientArgs) *serviceClient {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
s := &serviceClient{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
addr: addr,
|
||||
app: a,
|
||||
logFile: logFile,
|
||||
addr: args.addr,
|
||||
app: args.app,
|
||||
logFile: args.logFile,
|
||||
sendNotification: false,
|
||||
|
||||
showAdvancedSettings: showSettings,
|
||||
showNetworks: showNetworks,
|
||||
showAdvancedSettings: args.showSettings,
|
||||
showNetworks: args.showNetworks,
|
||||
update: version.NewUpdate("nb/client-ui"),
|
||||
}
|
||||
|
||||
s.eventHandler = newEventHandler(s)
|
||||
s.profileManager = profilemanager.NewProfileManager()
|
||||
s.setNewIcons()
|
||||
|
||||
switch {
|
||||
case showSettings:
|
||||
case args.showSettings:
|
||||
s.showSettingsUI()
|
||||
case showNetworks:
|
||||
case args.showNetworks:
|
||||
s.showNetworksUI()
|
||||
case showLoginURL:
|
||||
case args.showLoginURL:
|
||||
s.showLoginURL()
|
||||
case showDebug:
|
||||
case args.showDebug:
|
||||
s.showDebugUI()
|
||||
case args.showProfiles:
|
||||
s.showProfilesUI()
|
||||
}
|
||||
|
||||
return s
|
||||
@ -300,6 +353,8 @@ func newServiceClient(addr string, logFile string, a fyne.App, showSettings bool
|
||||
|
||||
func (s *serviceClient) setNewIcons() {
|
||||
s.icAbout = iconAbout
|
||||
s.icConnectedDot = iconConnectedDot
|
||||
s.icDisconnectedDot = iconDisconnectedDot
|
||||
if s.app.Settings().ThemeVariant() == theme.VariantDark {
|
||||
s.icConnected = iconConnectedDark
|
||||
s.icDisconnected = iconDisconnected
|
||||
@ -342,8 +397,7 @@ func (s *serviceClient) showSettingsUI() {
|
||||
s.wSettings.SetOnClosed(s.cancel)
|
||||
|
||||
s.iMngURL = widget.NewEntry()
|
||||
s.iConfigFile = widget.NewEntry()
|
||||
s.iConfigFile.Disable()
|
||||
|
||||
s.iLogFile = widget.NewEntry()
|
||||
s.iLogFile.Disable()
|
||||
s.iPreSharedKey = widget.NewPasswordEntry()
|
||||
@ -368,14 +422,22 @@ func (s *serviceClient) showSettingsUI() {
|
||||
|
||||
// getSettingsForm to embed it into settings window.
|
||||
func (s *serviceClient) getSettingsForm() *widget.Form {
|
||||
|
||||
var activeProfName string
|
||||
activeProf, err := s.profileManager.GetActiveProfile()
|
||||
if err != nil {
|
||||
log.Errorf("get active profile: %v", err)
|
||||
} else {
|
||||
activeProfName = activeProf.Name
|
||||
}
|
||||
return &widget.Form{
|
||||
Items: []*widget.FormItem{
|
||||
{Text: "Profile", Widget: widget.NewLabel(activeProfName)},
|
||||
{Text: "Quantum-Resistance", Widget: s.sRosenpassPermissive},
|
||||
{Text: "Interface Name", Widget: s.iInterfaceName},
|
||||
{Text: "Interface Port", Widget: s.iInterfacePort},
|
||||
{Text: "Management URL", Widget: s.iMngURL},
|
||||
{Text: "Pre-shared Key", Widget: s.iPreSharedKey},
|
||||
{Text: "Config File", Widget: s.iConfigFile},
|
||||
{Text: "Log File", Widget: s.iLogFile},
|
||||
{Text: "Network Monitor", Widget: s.sNetworkMonitor},
|
||||
{Text: "Disable DNS", Widget: s.sDisableDNS},
|
||||
@ -416,27 +478,67 @@ func (s *serviceClient) getSettingsForm() *widget.Form {
|
||||
s.managementURL = iMngURL
|
||||
s.preSharedKey = s.iPreSharedKey.Text
|
||||
|
||||
loginRequest := proto.LoginRequest{
|
||||
ManagementUrl: iMngURL,
|
||||
IsUnixDesktopClient: runtime.GOOS == "linux" || runtime.GOOS == "freebsd",
|
||||
RosenpassPermissive: &s.sRosenpassPermissive.Checked,
|
||||
InterfaceName: &s.iInterfaceName.Text,
|
||||
WireguardPort: &port,
|
||||
NetworkMonitor: &s.sNetworkMonitor.Checked,
|
||||
DisableDns: &s.sDisableDNS.Checked,
|
||||
DisableClientRoutes: &s.sDisableClientRoutes.Checked,
|
||||
DisableServerRoutes: &s.sDisableServerRoutes.Checked,
|
||||
BlockLanAccess: &s.sBlockLANAccess.Checked,
|
||||
}
|
||||
|
||||
if s.iPreSharedKey.Text != censoredPreSharedKey {
|
||||
loginRequest.OptionalPreSharedKey = &s.iPreSharedKey.Text
|
||||
}
|
||||
|
||||
if err := s.restartClient(&loginRequest); err != nil {
|
||||
log.Errorf("restarting client connection: %v", err)
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
log.Errorf("get current user: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
var req proto.SetConfigRequest
|
||||
req.ProfileName = activeProf.Name
|
||||
req.Username = currUser.Username
|
||||
|
||||
if iMngURL != "" {
|
||||
req.ManagementUrl = iMngURL
|
||||
}
|
||||
|
||||
req.RosenpassPermissive = &s.sRosenpassPermissive.Checked
|
||||
req.InterfaceName = &s.iInterfaceName.Text
|
||||
req.WireguardPort = &port
|
||||
req.NetworkMonitor = &s.sNetworkMonitor.Checked
|
||||
req.DisableDns = &s.sDisableDNS.Checked
|
||||
req.DisableClientRoutes = &s.sDisableClientRoutes.Checked
|
||||
req.DisableServerRoutes = &s.sDisableServerRoutes.Checked
|
||||
req.BlockLanAccess = &s.sBlockLANAccess.Checked
|
||||
|
||||
if s.iPreSharedKey.Text != censoredPreSharedKey {
|
||||
req.OptionalPreSharedKey = &s.iPreSharedKey.Text
|
||||
}
|
||||
|
||||
conn, err := s.getSrvClient(failFastTimeout)
|
||||
if err != nil {
|
||||
log.Errorf("get client: %v", err)
|
||||
dialog.ShowError(fmt.Errorf("Failed to connect to the service: %v", err), s.wSettings)
|
||||
return
|
||||
}
|
||||
_, err = conn.SetConfig(s.ctx, &req)
|
||||
if err != nil {
|
||||
log.Errorf("set config: %v", err)
|
||||
dialog.ShowError(fmt.Errorf("Failed to set configuration: %v", err), s.wSettings)
|
||||
return
|
||||
}
|
||||
|
||||
status, err := conn.Status(s.ctx, &proto.StatusRequest{})
|
||||
if err != nil {
|
||||
log.Errorf("get service status: %v", err)
|
||||
dialog.ShowError(fmt.Errorf("Failed to get service status: %v", err), s.wSettings)
|
||||
return
|
||||
}
|
||||
if status.Status == string(internal.StatusConnected) {
|
||||
// run down & up
|
||||
_, err = conn.Down(s.ctx, &proto.DownRequest{})
|
||||
if err != nil {
|
||||
log.Errorf("down service: %v", err)
|
||||
}
|
||||
|
||||
_, err = conn.Up(s.ctx, &proto.UpRequest{})
|
||||
if err != nil {
|
||||
log.Errorf("up service: %v", err)
|
||||
dialog.ShowError(fmt.Errorf("Failed to reconnect: %v", err), s.wSettings)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
OnCancel: func() {
|
||||
@ -452,8 +554,21 @@ func (s *serviceClient) login(openURL bool) (*proto.LoginResponse, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
activeProf, err := s.profileManager.GetActiveProfile()
|
||||
if err != nil {
|
||||
log.Errorf("get active profile: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get current user: %w", err)
|
||||
}
|
||||
|
||||
loginResp, err := conn.Login(s.ctx, &proto.LoginRequest{
|
||||
IsUnixDesktopClient: runtime.GOOS == "linux" || runtime.GOOS == "freebsd",
|
||||
ProfileName: &activeProf.Name,
|
||||
Username: &currUser.Username,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("login to management URL with: %v", err)
|
||||
@ -461,15 +576,9 @@ func (s *serviceClient) login(openURL bool) (*proto.LoginResponse, error) {
|
||||
}
|
||||
|
||||
if loginResp.NeedsSSOLogin && openURL {
|
||||
err = open.Run(loginResp.VerificationURIComplete)
|
||||
err = s.handleSSOLogin(loginResp, conn)
|
||||
if err != nil {
|
||||
log.Errorf("opening the verification uri in the browser failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = conn.WaitSSOLogin(s.ctx, &proto.WaitSSOLoginRequest{UserCode: loginResp.UserCode})
|
||||
if err != nil {
|
||||
log.Errorf("waiting sso login failed with: %v", err)
|
||||
log.Errorf("handle SSO login failed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -477,6 +586,34 @@ func (s *serviceClient) login(openURL bool) (*proto.LoginResponse, error) {
|
||||
return loginResp, nil
|
||||
}
|
||||
|
||||
func (s *serviceClient) handleSSOLogin(loginResp *proto.LoginResponse, conn proto.DaemonServiceClient) error {
|
||||
err := open.Run(loginResp.VerificationURIComplete)
|
||||
if err != nil {
|
||||
log.Errorf("opening the verification uri in the browser failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := conn.WaitSSOLogin(s.ctx, &proto.WaitSSOLoginRequest{UserCode: loginResp.UserCode})
|
||||
if err != nil {
|
||||
log.Errorf("waiting sso login failed with: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.Email != "" {
|
||||
err := s.profileManager.SetActiveProfileState(&profilemanager.ProfileState{
|
||||
Email: resp.Email,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warnf("failed to set profile state: %v", err)
|
||||
} else {
|
||||
s.mProfile.refresh()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *serviceClient) menuUpClick() error {
|
||||
systray.SetTemplateIcon(iconConnectingMacOS, s.icConnecting)
|
||||
conn, err := s.getSrvClient(defaultFailTimeout)
|
||||
@ -575,6 +712,7 @@ func (s *serviceClient) updateStatus() error {
|
||||
}
|
||||
systray.SetTooltip("NetBird (Connected)")
|
||||
s.mStatus.SetTitle("Connected")
|
||||
s.mStatus.SetIcon(s.icConnectedDot)
|
||||
s.mUp.Disable()
|
||||
s.mDown.Enable()
|
||||
s.mNetworks.Enable()
|
||||
@ -634,6 +772,7 @@ func (s *serviceClient) setDisconnectedStatus() {
|
||||
}
|
||||
systray.SetTooltip("NetBird (Disconnected)")
|
||||
s.mStatus.SetTitle("Disconnected")
|
||||
s.mStatus.SetIcon(s.icDisconnectedDot)
|
||||
s.mDown.Disable()
|
||||
s.mUp.Enable()
|
||||
s.mNetworks.Disable()
|
||||
@ -658,7 +797,13 @@ func (s *serviceClient) onTrayReady() {
|
||||
|
||||
// setup systray menu items
|
||||
s.mStatus = systray.AddMenuItem("Disconnected", "Disconnected")
|
||||
s.mStatus.SetIcon(s.icDisconnectedDot)
|
||||
s.mStatus.Disable()
|
||||
|
||||
profileMenuItem := systray.AddMenuItem("", "")
|
||||
emailMenuItem := systray.AddMenuItem("", "")
|
||||
s.mProfile = newProfileMenu(s.ctx, s.profileManager, *s.eventHandler, profileMenuItem, emailMenuItem, s.menuDownClick, s.menuUpClick, s.getSrvClient, s.loadSettings)
|
||||
|
||||
systray.AddSeparator()
|
||||
s.mUp = systray.AddMenuItem("Connect", "Connect")
|
||||
s.mDown = systray.AddMenuItem("Disconnect", "Disconnect")
|
||||
@ -790,7 +935,15 @@ func (s *serviceClient) getSrvClient(timeout time.Duration) (proto.DaemonService
|
||||
|
||||
// getSrvConfig from the service to show it in the settings window.
|
||||
func (s *serviceClient) getSrvConfig() {
|
||||
s.managementURL = internal.DefaultManagementURL
|
||||
s.managementURL = profilemanager.DefaultManagementURL
|
||||
|
||||
_, err := s.profileManager.GetActiveProfile()
|
||||
if err != nil {
|
||||
log.Errorf("get active profile: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
var cfg *profilemanager.Config
|
||||
|
||||
conn, err := s.getSrvClient(failFastTimeout)
|
||||
if err != nil {
|
||||
@ -798,48 +951,63 @@ func (s *serviceClient) getSrvConfig() {
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := conn.GetConfig(s.ctx, &proto.GetConfigRequest{})
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
log.Errorf("get current user: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
activeProf, err := s.profileManager.GetActiveProfile()
|
||||
if err != nil {
|
||||
log.Errorf("get active profile: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
srvCfg, err := conn.GetConfig(s.ctx, &proto.GetConfigRequest{
|
||||
ProfileName: activeProf.Name,
|
||||
Username: currUser.Username,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("get config settings from server: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.ManagementUrl != "" {
|
||||
s.managementURL = cfg.ManagementUrl
|
||||
cfg = protoConfigToConfig(srvCfg)
|
||||
|
||||
if cfg.ManagementURL.String() != "" {
|
||||
s.managementURL = cfg.ManagementURL.String()
|
||||
}
|
||||
s.preSharedKey = cfg.PreSharedKey
|
||||
s.RosenpassPermissive = cfg.RosenpassPermissive
|
||||
s.interfaceName = cfg.InterfaceName
|
||||
s.interfacePort = int(cfg.WireguardPort)
|
||||
s.interfaceName = cfg.WgIface
|
||||
s.interfacePort = cfg.WgPort
|
||||
|
||||
s.networkMonitor = cfg.NetworkMonitor
|
||||
s.disableDNS = cfg.DisableDns
|
||||
s.networkMonitor = *cfg.NetworkMonitor
|
||||
s.disableDNS = cfg.DisableDNS
|
||||
s.disableClientRoutes = cfg.DisableClientRoutes
|
||||
s.disableServerRoutes = cfg.DisableServerRoutes
|
||||
s.blockLANAccess = cfg.BlockLanAccess
|
||||
s.blockLANAccess = cfg.BlockLANAccess
|
||||
|
||||
if s.showAdvancedSettings {
|
||||
s.iMngURL.SetText(s.managementURL)
|
||||
s.iConfigFile.SetText(cfg.ConfigFile)
|
||||
s.iLogFile.SetText(cfg.LogFile)
|
||||
s.iPreSharedKey.SetText(cfg.PreSharedKey)
|
||||
s.iInterfaceName.SetText(cfg.InterfaceName)
|
||||
s.iInterfacePort.SetText(strconv.Itoa(int(cfg.WireguardPort)))
|
||||
s.iInterfaceName.SetText(cfg.WgIface)
|
||||
s.iInterfacePort.SetText(strconv.Itoa(cfg.WgPort))
|
||||
s.sRosenpassPermissive.SetChecked(cfg.RosenpassPermissive)
|
||||
if !cfg.RosenpassEnabled {
|
||||
s.sRosenpassPermissive.Disable()
|
||||
}
|
||||
s.sNetworkMonitor.SetChecked(cfg.NetworkMonitor)
|
||||
s.sDisableDNS.SetChecked(cfg.DisableDns)
|
||||
s.sNetworkMonitor.SetChecked(*cfg.NetworkMonitor)
|
||||
s.sDisableDNS.SetChecked(cfg.DisableDNS)
|
||||
s.sDisableClientRoutes.SetChecked(cfg.DisableClientRoutes)
|
||||
s.sDisableServerRoutes.SetChecked(cfg.DisableServerRoutes)
|
||||
s.sBlockLANAccess.SetChecked(cfg.BlockLanAccess)
|
||||
s.sBlockLANAccess.SetChecked(cfg.BlockLANAccess)
|
||||
}
|
||||
|
||||
if s.mNotifications == nil {
|
||||
return
|
||||
}
|
||||
if cfg.DisableNotifications {
|
||||
if cfg.DisableNotifications != nil && *cfg.DisableNotifications {
|
||||
s.mNotifications.Uncheck()
|
||||
} else {
|
||||
s.mNotifications.Check()
|
||||
@ -849,6 +1017,58 @@ func (s *serviceClient) getSrvConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
func protoConfigToConfig(cfg *proto.GetConfigResponse) *profilemanager.Config {
|
||||
|
||||
var config profilemanager.Config
|
||||
|
||||
if cfg.ManagementUrl != "" {
|
||||
parsed, err := url.Parse(cfg.ManagementUrl)
|
||||
if err != nil {
|
||||
log.Errorf("parse management URL: %v", err)
|
||||
} else {
|
||||
config.ManagementURL = parsed
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.PreSharedKey != "" {
|
||||
if cfg.PreSharedKey != censoredPreSharedKey {
|
||||
config.PreSharedKey = cfg.PreSharedKey
|
||||
} else {
|
||||
config.PreSharedKey = ""
|
||||
}
|
||||
}
|
||||
if cfg.AdminURL != "" {
|
||||
parsed, err := url.Parse(cfg.AdminURL)
|
||||
if err != nil {
|
||||
log.Errorf("parse admin URL: %v", err)
|
||||
} else {
|
||||
config.AdminURL = parsed
|
||||
}
|
||||
}
|
||||
|
||||
config.WgIface = cfg.InterfaceName
|
||||
if cfg.WireguardPort != 0 {
|
||||
config.WgPort = int(cfg.WireguardPort)
|
||||
} else {
|
||||
config.WgPort = iface.DefaultWgPort
|
||||
}
|
||||
|
||||
config.DisableAutoConnect = cfg.DisableAutoConnect
|
||||
config.ServerSSHAllowed = &cfg.ServerSSHAllowed
|
||||
config.RosenpassEnabled = cfg.RosenpassEnabled
|
||||
config.RosenpassPermissive = cfg.RosenpassPermissive
|
||||
config.DisableNotifications = &cfg.DisableNotifications
|
||||
config.LazyConnectionEnabled = cfg.LazyConnectionEnabled
|
||||
config.BlockInbound = cfg.BlockInbound
|
||||
config.NetworkMonitor = &cfg.NetworkMonitor
|
||||
config.DisableDNS = cfg.DisableDns
|
||||
config.DisableClientRoutes = cfg.DisableClientRoutes
|
||||
config.DisableServerRoutes = cfg.DisableServerRoutes
|
||||
config.BlockLANAccess = cfg.BlockLanAccess
|
||||
|
||||
return &config
|
||||
}
|
||||
|
||||
func (s *serviceClient) onUpdateAvailable() {
|
||||
s.updateIndicationLock.Lock()
|
||||
defer s.updateIndicationLock.Unlock()
|
||||
@ -880,7 +1100,22 @@ func (s *serviceClient) loadSettings() {
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := conn.GetConfig(s.ctx, &proto.GetConfigRequest{})
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
log.Errorf("get current user: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
activeProf, err := s.profileManager.GetActiveProfile()
|
||||
if err != nil {
|
||||
log.Errorf("get active profile: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := conn.GetConfig(s.ctx, &proto.GetConfigRequest{
|
||||
ProfileName: activeProf.Name,
|
||||
Username: currUser.Username,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("get config settings from server: %v", err)
|
||||
return
|
||||
@ -936,41 +1171,37 @@ func (s *serviceClient) updateConfig() error {
|
||||
blockInbound := s.mBlockInbound.Checked()
|
||||
notificationsDisabled := !s.mNotifications.Checked()
|
||||
|
||||
loginRequest := proto.LoginRequest{
|
||||
IsUnixDesktopClient: runtime.GOOS == "linux" || runtime.GOOS == "freebsd",
|
||||
activeProf, err := s.profileManager.GetActiveProfile()
|
||||
if err != nil {
|
||||
log.Errorf("get active profile: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
log.Errorf("get current user: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
conn, err := s.getSrvClient(failFastTimeout)
|
||||
if err != nil {
|
||||
log.Errorf("get client: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
req := proto.SetConfigRequest{
|
||||
ProfileName: activeProf.Name,
|
||||
Username: currUser.Username,
|
||||
DisableAutoConnect: &disableAutoStart,
|
||||
ServerSSHAllowed: &sshAllowed,
|
||||
RosenpassEnabled: &rosenpassEnabled,
|
||||
DisableAutoConnect: &disableAutoStart,
|
||||
DisableNotifications: ¬ificationsDisabled,
|
||||
LazyConnectionEnabled: &lazyConnectionEnabled,
|
||||
BlockInbound: &blockInbound,
|
||||
DisableNotifications: ¬ificationsDisabled,
|
||||
}
|
||||
|
||||
if err := s.restartClient(&loginRequest); err != nil {
|
||||
log.Errorf("restarting client connection: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// restartClient restarts the client connection.
|
||||
func (s *serviceClient) restartClient(loginRequest *proto.LoginRequest) error {
|
||||
ctx, cancel := context.WithTimeout(s.ctx, defaultFailTimeout)
|
||||
defer cancel()
|
||||
|
||||
client, err := s.getSrvClient(failFastTimeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = client.Login(ctx, loginRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = client.Up(ctx, &proto.UpRequest{})
|
||||
if err != nil {
|
||||
if _, err := conn.SetConfig(s.ctx, &req); err != nil {
|
||||
log.Errorf("set config settings on server: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user