|
@@ -39,7 +39,7 @@ type ShareConfig struct {
|
|
|
GuestOk bool
|
|
|
}
|
|
|
|
|
|
-func NewSambaShareManager() (*ShareManager, error) {
|
|
|
+func NewSambaShareManager(userHandler *user.UserHandler) (*ShareManager, error) {
|
|
|
if runtime.GOOS == "linux" {
|
|
|
//Check if samba installed
|
|
|
if !utils.FileExists("/bin/smbcontrol") {
|
|
@@ -51,10 +51,11 @@ func NewSambaShareManager() (*ShareManager, error) {
|
|
|
return &ShareManager{
|
|
|
SambaConfigPath: "/etc/samba/smb.conf",
|
|
|
BackupDir: "./backup",
|
|
|
+ UserHandler: userHandler,
|
|
|
}, nil
|
|
|
}
|
|
|
|
|
|
-// ReadSambaShares reads the smb.conf file and extracts all existing shares
|
|
|
+// ReadSambaShares reads / lists the smb.conf file and extracts all existing shares
|
|
|
func (s *ShareManager) ReadSambaShares() ([]ShareConfig, error) {
|
|
|
file, err := os.Open(s.SambaConfigPath)
|
|
|
if err != nil {
|
|
@@ -162,7 +163,7 @@ func (s *ShareManager) CreateNewSambaShare(shareToCreate *ShareConfig) error {
|
|
|
shareExists := false
|
|
|
shareNameSection := fmt.Sprintf("[%s]", shareToCreate.Name)
|
|
|
for scanner.Scan() {
|
|
|
- if strings.TrimSpace(scanner.Text()) == shareNameSection {
|
|
|
+ if strings.EqualFold(strings.TrimSpace(scanner.Text()), shareNameSection) {
|
|
|
shareExists = true
|
|
|
break
|
|
|
}
|
|
@@ -196,6 +197,18 @@ func (s *ShareManager) CreateNewSambaShare(shareToCreate *ShareConfig) error {
|
|
|
|
|
|
// RemoveSambaShareConfig removes the Samba share configuration from smb.conf
|
|
|
func (s *ShareManager) RemoveSambaShareConfig(shareName string) error {
|
|
|
+ // Check if the share exists
|
|
|
+ shareExists, err := s.ShareExists(shareName)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if !shareExists {
|
|
|
+ return errors.New("share not exists")
|
|
|
+ }
|
|
|
+
|
|
|
+ //Convert the sharename to correct case for matching
|
|
|
+ shareName = s.getCorrectCaseForShareName(shareName)
|
|
|
+
|
|
|
// Open the smb.conf file for reading
|
|
|
file, err := os.Open(s.SambaConfigPath)
|
|
|
if err != nil {
|
|
@@ -219,7 +232,10 @@ func (s *ShareManager) RemoveSambaShareConfig(shareName string) error {
|
|
|
if strings.HasPrefix(line, "["+shareName+"]") {
|
|
|
// Skip the lines until the next section
|
|
|
for scanner.Scan() {
|
|
|
- if strings.HasPrefix(scanner.Text(), "[") {
|
|
|
+ checkingLine := scanner.Text()
|
|
|
+ if strings.HasPrefix(checkingLine, "[") {
|
|
|
+ //The header of the next section is also need to be kept
|
|
|
+ fmt.Fprintln(tmpFile, checkingLine)
|
|
|
break
|
|
|
}
|
|
|
}
|
|
@@ -272,7 +288,7 @@ func (s *ShareManager) ShareExists(shareName string) (bool, error) {
|
|
|
scanner := bufio.NewScanner(file)
|
|
|
shareNameSection := fmt.Sprintf("[%s]", shareName)
|
|
|
for scanner.Scan() {
|
|
|
- if strings.TrimSpace(scanner.Text()) == shareNameSection {
|
|
|
+ if strings.EqualFold(shareNameSection, strings.TrimSpace(scanner.Text())) {
|
|
|
return true, nil
|
|
|
}
|
|
|
}
|
|
@@ -325,77 +341,118 @@ func (s *ShareManager) BackupSmbConf() error {
|
|
|
|
|
|
// Add a new user to smb.conf share by name
|
|
|
func (s *ShareManager) AddUserToSambaShare(shareName, username string) error {
|
|
|
- // Open the smb.conf file for reading
|
|
|
- file, err := os.Open(s.SambaConfigPath)
|
|
|
+ targetShare, err := s.GetShareByName(shareName)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to open smb.conf: %v", err)
|
|
|
+ return err
|
|
|
}
|
|
|
- defer file.Close()
|
|
|
|
|
|
- var lines []string
|
|
|
- var insideShare bool
|
|
|
- var shareExists bool
|
|
|
- var userAdded bool
|
|
|
+ if s.UserCanAccessShare(targetShare, username) {
|
|
|
+ //User already have no access to this share, no need to delete
|
|
|
+ return nil
|
|
|
+ }
|
|
|
|
|
|
- scanner := bufio.NewScanner(file)
|
|
|
- for scanner.Scan() {
|
|
|
- line := scanner.Text()
|
|
|
- lines = append(lines, line)
|
|
|
+ //User not in this share. Append user name in this valid users
|
|
|
+ targetShare.ValidUsers = append(targetShare.ValidUsers, username)
|
|
|
|
|
|
- // Check if we are inside the specified share section
|
|
|
- if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
|
|
- if insideShare && shareExists && !userAdded {
|
|
|
- // Add the username to the valid users list
|
|
|
- lines = append(lines, " valid users = @"+username)
|
|
|
- userAdded = true
|
|
|
- }
|
|
|
- insideShare = false
|
|
|
- }
|
|
|
+ //Delete the old one and create the new share with updated user list
|
|
|
+ err = s.RemoveSambaShareConfig(shareName)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
|
|
|
- if strings.TrimSpace(line) == fmt.Sprintf("[%s]", shareName) {
|
|
|
- insideShare = true
|
|
|
- shareExists = true
|
|
|
- }
|
|
|
+ err = s.CreateNewSambaShare(targetShare)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
|
|
|
- if insideShare && strings.HasPrefix(strings.TrimSpace(line), "valid users =") {
|
|
|
- // Check if the username already exists in the valid users list
|
|
|
- validUsersLine := strings.TrimSpace(line)
|
|
|
- if !strings.Contains(validUsersLine, username) {
|
|
|
- lines[len(lines)-1] = validUsersLine + ", @" + username
|
|
|
- userAdded = true
|
|
|
- }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// Return if the user can access this samba share
|
|
|
+func (s *ShareManager) UserCanAccessShare(targetSmbShare *ShareConfig, username string) bool {
|
|
|
+ return utils.StringInArray(targetSmbShare.ValidUsers, username)
|
|
|
+}
|
|
|
+
|
|
|
+// Get a list of shares that this user have access to
|
|
|
+func (s *ShareManager) GetUsersShare(username string) ([]*ShareConfig, error) {
|
|
|
+ allShares, err := s.ReadSambaShares()
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ userAccessibleShares := []*ShareConfig{}
|
|
|
+ for _, thisShare := range allShares {
|
|
|
+ if s.UserCanAccessShare(&thisShare, username) {
|
|
|
+ thisShareObject := thisShare
|
|
|
+ userAccessibleShares = append(userAccessibleShares, &thisShareObject)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if err := scanner.Err(); err != nil {
|
|
|
- return fmt.Errorf("error reading smb.conf: %v", err)
|
|
|
+ return userAccessibleShares, nil
|
|
|
+}
|
|
|
+
|
|
|
+// Remove a user from smb.conf share by name
|
|
|
+func (s *ShareManager) RemoveUserFromSambaShare(shareName, username string) error {
|
|
|
+ targetShare, err := s.GetShareByName(shareName)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
}
|
|
|
|
|
|
- if !shareExists {
|
|
|
- return fmt.Errorf("share [%s] not found in smb.conf", shareName)
|
|
|
+ if !s.UserCanAccessShare(targetShare, username) {
|
|
|
+ //User already have no access to this share, no need to delete
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
- if !userAdded {
|
|
|
- // If no valid users line was found, add the username to the share
|
|
|
- lines = append(lines, fmt.Sprintf("[%s]", shareName))
|
|
|
- lines = append(lines, " valid users = @"+username)
|
|
|
+ if len(targetShare.ValidUsers) == 1 && strings.EqualFold(targetShare.ValidUsers[0], username) {
|
|
|
+ //This user is the only person who can access this share
|
|
|
+ //Remove the share entirely
|
|
|
+ //Delete the old one and create the new share with updated user list
|
|
|
+ err = s.RemoveSambaShareConfig(shareName)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
- // Write the updated configuration back to the smb.conf file
|
|
|
- outputFile, err := os.Create(s.SambaConfigPath)
|
|
|
+ //User is in this share but this share contain other users.
|
|
|
+ err = s.RemoveSambaShareConfig(shareName)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("failed to open smb.conf for writing: %v", err)
|
|
|
+ return err
|
|
|
}
|
|
|
- defer outputFile.Close()
|
|
|
|
|
|
- writer := bufio.NewWriter(outputFile)
|
|
|
- for _, line := range lines {
|
|
|
- _, err := writer.WriteString(line + "\n")
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("error writing to smb.conf: %v", err)
|
|
|
+ //Create a new valid user list
|
|
|
+ newShareValidUsers := []string{}
|
|
|
+ for _, validUser := range targetShare.ValidUsers {
|
|
|
+ if !strings.EqualFold(validUser, username) {
|
|
|
+ newShareValidUsers = append(newShareValidUsers, validUser)
|
|
|
}
|
|
|
}
|
|
|
- writer.Flush()
|
|
|
+ targetShare.ValidUsers = newShareValidUsers
|
|
|
+
|
|
|
+ //Create the share
|
|
|
+ err = s.CreateNewSambaShare(targetShare)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
+
|
|
|
+// Get a share by name
|
|
|
+func (s *ShareManager) GetShareByName(shareName string) (*ShareConfig, error) {
|
|
|
+ allShares, err := s.ReadSambaShares()
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, thisShare := range allShares {
|
|
|
+ if strings.EqualFold(shareName, thisShare.Name) {
|
|
|
+ return &thisShare, nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil, errors.New("target share not found")
|
|
|
+
|
|
|
+}
|