// system/client.go package system import ( "bufio" "encoding/json" "fmt" "net" "strings" ) type SystemClient struct { socketPath string } type Command struct { Action string `json:"action"` Params map[string]interface{} `json:"params"` } type Response struct { Success bool `json:"success"` Data interface{} `json:"data"` Error string `json:"error,omitempty"` } type User struct { Username string `json:"username"` UID string `json:"uid"` GID string `json:"gid"` HomeDir string `json:"home_dir"` Shell string `json:"shell"` } type Group struct { GroupName string `json:"groupName"` } type SambaConnection struct { PID string `json:"pid"` Username string `json:"username"` Group string `json:"group"` Machine string `json:"machine"` Protocol string `json:"protocol"` Folder string `json:"folder"` } func NewSystemClient(socketPath string) *SystemClient { return &SystemClient{ socketPath: socketPath, } } func (c *SystemClient) sendCommand(cmd Command) (*Response, error) { // 連接到 Unix socket conn, err := net.Dial("unix", c.socketPath) if err != nil { return nil, fmt.Errorf("failed to connect to socket: %v", err) } defer conn.Close() // 發送命令 encoder := json.NewEncoder(conn) if err := encoder.Encode(cmd); err != nil { return nil, fmt.Errorf("failed to encode command: %v", err) } // 讀取響應 decoder := json.NewDecoder(conn) var response Response if err := decoder.Decode(&response); err != nil { return nil, fmt.Errorf("failed to decode response: %v", err) } return &response, nil } func (c *SystemClient) GetUsers() ([]User, error) { resp, err := c.sendCommand(Command{ Action: "get_users", Params: nil, }) if err != nil { return nil, err } if !resp.Success { return nil, fmt.Errorf(resp.Error) } var users []User dataStr, ok := resp.Data.(string) if !ok { fmt.Println("Error: Data is not a string") return users, nil } scanner := bufio.NewScanner(strings.NewReader(dataStr)) for scanner.Scan() { line := scanner.Text() parts := strings.Split(line, ":") if len(parts) < 7 { continue // Skip malformed lines } username := parts[0] uid := parts[2] gid := parts[3] homeDir := parts[5] shell := parts[6] user := User{ Username: username, UID: uid, GID: gid, HomeDir: homeDir, Shell: shell, } users = append(users, user) } if err := scanner.Err(); err != nil { fmt.Println("Error reading command output:", err) return users, nil } // Marshal to JSON and print _, err = json.MarshalIndent(users, "", " ") if err != nil { fmt.Println("Error marshalling to JSON:", err) return users, nil } return users, nil } func (c *SystemClient) GetGroups() ([]Group, error) { resp, err := c.sendCommand(Command{ Action: "get_groups", Params: nil, }) if err != nil { return nil, err } if !resp.Success { return nil, fmt.Errorf(resp.Error) } var groups []Group dataStr, ok := resp.Data.(string) if !ok { fmt.Println("Error: Data is not a string") return groups, nil } scanner := bufio.NewScanner(strings.NewReader(dataStr)) for scanner.Scan() { line := scanner.Text() group := Group{ GroupName: line, } groups = append(groups, group) } if err := scanner.Err(); err != nil { fmt.Println("Error reading command output:", err) return groups, nil } // Marshal to JSON and print _, err = json.MarshalIndent(groups, "", " ") if err != nil { fmt.Println("Error marshalling to JSON:", err) return groups, nil } return groups, nil } func (c *SystemClient) GetUserGroups(username string) ([]Group, error) { resp, err := c.sendCommand(Command{ Action: "get_user_groups", Params: map[string]interface{}{ "username": username, }, }) if err != nil { return nil, err } if !resp.Success { return nil, fmt.Errorf(resp.Error) } var groups []Group dataStr, ok := resp.Data.([]interface{}) if !ok { fmt.Println("Error: Data is not a string") return groups, nil } for _, data := range dataStr { str, ok := data.(string) if !ok { return nil, fmt.Errorf("data contains non-string element") } group := Group{ GroupName: str, } groups = append(groups, group) } // Marshal to JSON and print _, err = json.MarshalIndent(groups, "", " ") if err != nil { fmt.Println("Error marshalling to JSON:", err) return groups, nil } return groups, nil } func (c *SystemClient) AddUserToGroups(username string, groups []string) error { // Loop through the groups and add the user to each group for _, group := range groups { // Implement logic to add the user to the group resp, err := c.sendCommand(Command{ Action: "add_user_to_group", Params: map[string]interface{}{ "username": username, "group": group, }, }) if err != nil { return err } if !resp.Success { return fmt.Errorf(resp.Error) } } return nil } func (c *SystemClient) RemoveUserFromGroup(username, group string) error { resp, err := c.sendCommand(Command{ Action: "remove_user_from_group", Params: map[string]interface{}{ "username": username, "group": group, }, }) if err != nil { return err } if !resp.Success { return fmt.Errorf(resp.Error) } return nil } func (c *SystemClient) CreateUser(username, password string, group string, isAdmin bool, shell string) error { resp, err := c.sendCommand(Command{ Action: "create_user", Params: map[string]interface{}{ "username": username, "password": password, "group": group, "is_admin": isAdmin, "shell": shell, }, }) if err != nil { return err } if !resp.Success { return fmt.Errorf(resp.Error) } return nil } func (c *SystemClient) ModifyUserPasswd(username string, password string) error { resp, err := c.sendCommand(Command{ Action: "modify_user_passwd", Params: map[string]interface{}{ "username": username, "password": password, }, }) if err != nil { return err } if !resp.Success { return fmt.Errorf(resp.Error) } return nil } func (c *SystemClient) DeleteUser(username string) error { resp, err := c.sendCommand(Command{ Action: "delete_user", Params: map[string]interface{}{ "username": username, }, }) if err != nil { return err } if !resp.Success { return fmt.Errorf(resp.Error) } return nil } func (c *SystemClient) GetSambaConnections() ([]SambaConnection, error) { resp, err := c.sendCommand(Command{ Action: "get_samba_status", Params: nil, }) if err != nil { return nil, err } if !resp.Success { return nil, fmt.Errorf(resp.Error) } var connections []SambaConnection data, err := json.Marshal(resp.Data) if err != nil { return nil, err } if err := json.Unmarshal(data, &connections); err != nil { return nil, err } return connections, nil } func (c *SystemClient) GetSambaGlobalSetting() (string, error) { resp, err := c.sendCommand(Command{ Action: "get_samba_settings", Params: nil, }) if err != nil { return "", err } if !resp.Success { return "", fmt.Errorf(resp.Error) } settings_str, ok := resp.Data.(string) if !ok { fmt.Println("Error: Data is not a string") return "", nil } return settings_str, nil } func (c *SystemClient) GetSambaSectionSetting() (string, error) { resp, err := c.sendCommand(Command{ Action: "get_samba_settings", Params: nil, }) if err != nil { return "", err } if !resp.Success { return "", fmt.Errorf(resp.Error) } settings_str, ok := resp.Data.(string) if !ok { fmt.Println("Error: Data is not a string") return "", nil } return settings_str, nil } func (c *SystemClient) UpdateSambaSectionSetting(fullSectionSettingsJSON string) error { // Step 1: Get all current settings settings, err := c.GetSambaSectionSetting() if err != nil { return fmt.Errorf("failed to fetch current Samba settings: %v", err) } // Step 2: Parse the settings JSON string into a map var settingsMap map[string]interface{} if err := json.Unmarshal([]byte(settings), &settingsMap); err != nil { return fmt.Errorf("failed to parse Samba settings JSON: %v", err) } // Step 3: Parse the full new section settings JSON var newSectionSettings map[string]interface{} if err := json.Unmarshal([]byte(fullSectionSettingsJSON), &newSectionSettings); err != nil { return fmt.Errorf("failed to parse new section settings JSON: %v", err) } // Step 4: Replace the entire "sections" field settingsMap["sections"] = newSectionSettings // Step 5: Convert updated settings back to JSON updatedSettings, err := json.Marshal(settingsMap) if err != nil { return fmt.Errorf("failed to marshal updated settings to JSON: %v", err) } // Step 6: Send the updated settings using `update_section_setting` resp, err := c.sendCommand(Command{ Action: "update_section_setting", Params: map[string]interface{}{"config": string(updatedSettings)}, }) if err != nil { return fmt.Errorf("failed to send updated settings: %v", err) } if !resp.Success { return fmt.Errorf("failed to update section settings: %v", resp.Error) } return nil } func (c *SystemClient) UpdateSambaGlobalSetting(fullGlobalSettingsJSON string) error { // Step 1: Get all current settings settings, err := c.GetSambaGlobalSetting() if err != nil { return fmt.Errorf("failed to fetch current Samba settings: %v", err) } // Step 2: Parse the settings JSON string into a map var settingsMap map[string]interface{} if err := json.Unmarshal([]byte(settings), &settingsMap); err != nil { return fmt.Errorf("failed to parse Samba settings JSON: %v", err) } // Step 3: Parse the full new global settings JSON var newGlobalSettings map[string]interface{} if err := json.Unmarshal([]byte(fullGlobalSettingsJSON), &newGlobalSettings); err != nil { return fmt.Errorf("failed to parse new global settings JSON: %v", err) } // Step 4: Replace the entire "global" field settingsMap["global"] = newGlobalSettings // Step 5: Convert updated settings back to JSON updatedSettings, err := json.Marshal(settingsMap) if err != nil { return fmt.Errorf("failed to marshal updated settings to JSON: %v", err) } // Step 6: Send the updated settings using `update_section_setting` resp, err := c.sendCommand(Command{ Action: "update_section_setting", Params: map[string]interface{}{"config": string(updatedSettings)}, }) if err != nil { return fmt.Errorf("failed to send updated settings: %v", err) } if !resp.Success { return fmt.Errorf("failed to update global settings: %v", resp.Error) } return nil } func (c *SystemClient) GetSambaServiceInfo() (string, error) { resp, err := c.sendCommand(Command{ Action: "get_samba_service_info", Params: nil, }) if err != nil { return "", err } if !resp.Success { return "", fmt.Errorf(resp.Error) } dataStr, ok := resp.Data.(string) if !ok { fmt.Println("Error: Data is not a string") return "", nil } return dataStr, nil } func (c *SystemClient) RestartSambaService() error { resp, err := c.sendCommand(Command{ Action: "restart_samba_service", Params: nil, }) if err != nil { return err } if !resp.Success { return fmt.Errorf(resp.Error) } return nil }