88 lines
2.8 KiB
Go
88 lines
2.8 KiB
Go
package samba
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/example/storage-appliance/internal/domain"
|
|
"github.com/example/storage-appliance/internal/infra/osexec"
|
|
)
|
|
|
|
type Adapter struct {
|
|
Runner osexec.Runner
|
|
IncludePath string
|
|
}
|
|
|
|
func NewAdapter(runner osexec.Runner, includePath string) *Adapter {
|
|
if includePath == "" {
|
|
includePath = "/etc/samba/smb.conf.d/appliance.conf"
|
|
}
|
|
return &Adapter{Runner: runner, IncludePath: includePath}
|
|
}
|
|
|
|
// RenderConf writes the Samba include file for appliance-managed shares
|
|
func (a *Adapter) RenderConf(ctx context.Context, shares []domain.Share) error {
|
|
var lines []string
|
|
lines = append(lines, "# Appliance-managed SMB share configuration")
|
|
for _, s := range shares {
|
|
if s.Type != "smb" {
|
|
continue
|
|
}
|
|
opts := []string{"path = " + s.Path}
|
|
// parse options if stored in s.Name or s.Config; fallback to broad default
|
|
// s.Config may have read-only or allowed users
|
|
if ro, ok := s.Config["read_only"]; ok && ro == "true" {
|
|
opts = append(opts, "read only = yes")
|
|
} else {
|
|
opts = append(opts, "read only = no")
|
|
}
|
|
if users, ok := s.Config["allowed_users"]; ok {
|
|
opts = append(opts, "valid users = "+users)
|
|
}
|
|
// write section
|
|
lines = append(lines, fmt.Sprintf("[%s]", s.Name))
|
|
for _, l := range opts {
|
|
lines = append(lines, l)
|
|
}
|
|
lines = append(lines, "")
|
|
}
|
|
content := strings.Join(lines, "\n") + "\n"
|
|
dir := filepath.Dir(a.IncludePath)
|
|
tmp := filepath.Join(dir, ".appliance.smb.tmp")
|
|
if err := os.WriteFile(tmp, []byte(content), 0644); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Rename(tmp, a.IncludePath); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Reload reloads or restarts samba to apply config
|
|
func (a *Adapter) Reload(ctx context.Context) error {
|
|
// try to reload first
|
|
_, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "systemctl", "reload", "smbd")
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
// fallback to restart
|
|
_, stderr, _, err = osexec.ExecWithRunner(a.Runner, ctx, "systemctl", "restart", "smbd")
|
|
if err != nil {
|
|
return fmt.Errorf("samba reload/restart failed: %s", stderr)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CreateSambaUser optional: stub for creating a local samba user mapped to appliance user
|
|
func (a *Adapter) CreateSambaUser(ctx context.Context, user, password string) error {
|
|
// This is optional - we use smbpasswd command in production; stub for now
|
|
_, stderr, _, err := osexec.ExecWithRunner(a.Runner, ctx, "smbpasswd", "-a", user)
|
|
if err != nil {
|
|
return fmt.Errorf("smbpasswd failed: %s", stderr)
|
|
}
|
|
return nil
|
|
}
|