mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
[client] Feat: Support Multiple Profiles (#3980)
[client] Feat: Support Multiple Profiles (#3980)
This commit is contained in:
133
client/internal/profilemanager/profilemanager.go
Normal file
133
client/internal/profilemanager/profilemanager.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package profilemanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultProfileName = "default"
|
||||
activeProfileStateFilename = "active_profile.txt"
|
||||
)
|
||||
|
||||
type Profile struct {
|
||||
Name string
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
func (p *Profile) FilePath() (string, error) {
|
||||
if p.Name == "" {
|
||||
return "", fmt.Errorf("active profile name is empty")
|
||||
}
|
||||
|
||||
if p.Name == defaultProfileName {
|
||||
return DefaultConfigPath, nil
|
||||
}
|
||||
|
||||
username, err := user.Current()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get current user: %w", err)
|
||||
}
|
||||
|
||||
configDir, err := getConfigDirForUser(username.Username)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get config directory for user %s: %w", username.Username, err)
|
||||
}
|
||||
|
||||
return filepath.Join(configDir, p.Name+".json"), nil
|
||||
}
|
||||
|
||||
func (p *Profile) IsDefault() bool {
|
||||
return p.Name == defaultProfileName
|
||||
}
|
||||
|
||||
type ProfileManager struct {
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewProfileManager() *ProfileManager {
|
||||
return &ProfileManager{}
|
||||
}
|
||||
|
||||
func (pm *ProfileManager) GetActiveProfile() (*Profile, error) {
|
||||
pm.mu.Lock()
|
||||
defer pm.mu.Unlock()
|
||||
|
||||
prof := pm.getActiveProfileState()
|
||||
return &Profile{Name: prof}, nil
|
||||
}
|
||||
|
||||
func (pm *ProfileManager) SwitchProfile(profileName string) error {
|
||||
profileName = sanitizeProfileName(profileName)
|
||||
|
||||
if err := pm.setActiveProfileState(profileName); err != nil {
|
||||
return fmt.Errorf("failed to switch profile: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// sanitizeProfileName sanitizes the username by removing any invalid characters and spaces.
|
||||
func sanitizeProfileName(name string) string {
|
||||
return strings.Map(func(r rune) rune {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' {
|
||||
return r
|
||||
}
|
||||
// drop everything else
|
||||
return -1
|
||||
}, name)
|
||||
}
|
||||
|
||||
func (pm *ProfileManager) getActiveProfileState() string {
|
||||
|
||||
configDir, err := getConfigDir()
|
||||
if err != nil {
|
||||
log.Warnf("failed to get config directory: %v", err)
|
||||
return defaultProfileName
|
||||
}
|
||||
|
||||
statePath := filepath.Join(configDir, activeProfileStateFilename)
|
||||
|
||||
prof, err := os.ReadFile(statePath)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Warnf("failed to read active profile state: %v", err)
|
||||
} else {
|
||||
if err := pm.setActiveProfileState(defaultProfileName); err != nil {
|
||||
log.Warnf("failed to set default profile state: %v", err)
|
||||
}
|
||||
}
|
||||
return defaultProfileName
|
||||
}
|
||||
profileName := strings.TrimSpace(string(prof))
|
||||
|
||||
if profileName == "" {
|
||||
log.Warnf("active profile state is empty, using default profile: %s", defaultProfileName)
|
||||
return defaultProfileName
|
||||
}
|
||||
|
||||
return profileName
|
||||
}
|
||||
|
||||
func (pm *ProfileManager) setActiveProfileState(profileName string) error {
|
||||
|
||||
configDir, err := getConfigDir()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get config directory: %w", err)
|
||||
}
|
||||
|
||||
statePath := filepath.Join(configDir, activeProfileStateFilename)
|
||||
|
||||
err = os.WriteFile(statePath, []byte(profileName), 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write active profile state: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user