feat: initial FTP Server for Windows with web admin panel
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Config represents the application configuration
|
||||
type Config struct {
|
||||
mu sync.RWMutex `json:"-"`
|
||||
FTP FTPConfig `json:"ftp"`
|
||||
Web WebConfig `json:"web"`
|
||||
Admin AdminConfig `json:"admin"`
|
||||
FTPUsers []FTPUser `json:"ftpUsers"`
|
||||
}
|
||||
|
||||
// FTPConfig holds FTP server settings
|
||||
type FTPConfig struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
PassiveMin int `json:"passivePortMin"`
|
||||
PassiveMax int `json:"passivePortMax"`
|
||||
RootDir string `json:"rootDir"`
|
||||
}
|
||||
|
||||
// WebConfig holds web admin panel settings
|
||||
type WebConfig struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
// AdminConfig holds admin credentials
|
||||
type AdminConfig struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// FTPUser represents an FTP user account
|
||||
type FTPUser struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
HomeDir string `json:"homeDir"`
|
||||
Write bool `json:"write"`
|
||||
}
|
||||
|
||||
// DefaultConfig returns a default configuration
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
FTP: FTPConfig{
|
||||
Host: "0.0.0.0",
|
||||
Port: 2121,
|
||||
PassiveMin: 50000,
|
||||
PassiveMax: 50100,
|
||||
RootDir: "./ftp_root",
|
||||
},
|
||||
Web: WebConfig{
|
||||
Host: "0.0.0.0",
|
||||
Port: 8080,
|
||||
},
|
||||
Admin: AdminConfig{
|
||||
Username: "admin",
|
||||
Password: "admin123",
|
||||
},
|
||||
FTPUsers: []FTPUser{
|
||||
{
|
||||
Username: "ftpuser",
|
||||
Password: "ftp123",
|
||||
HomeDir: "./ftp_root",
|
||||
Write: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Load loads configuration from a file
|
||||
func Load(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
cfg := DefaultConfig()
|
||||
if saveErr := cfg.Save(path); saveErr != nil {
|
||||
return nil, saveErr
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
if err := json.Unmarshal(data, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
// Save saves configuration to a file
|
||||
func (c *Config) Save(path string) error {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
data, err := json.MarshalIndent(c, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(path, data, 0644)
|
||||
}
|
||||
|
||||
// GetFTPUser finds an FTP user by username
|
||||
func (c *Config) GetFTPUser(username string) *FTPUser {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
for i := range c.FTPUsers {
|
||||
if c.FTPUsers[i].Username == username {
|
||||
return &c.FTPUsers[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddFTPUser adds a new FTP user
|
||||
func (c *Config) AddFTPUser(user FTPUser) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.FTPUsers = append(c.FTPUsers, user)
|
||||
}
|
||||
|
||||
// DeleteFTPUser removes an FTP user by username
|
||||
func (c *Config) DeleteFTPUser(username string) bool {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for i, u := range c.FTPUsers {
|
||||
if u.Username == username {
|
||||
c.FTPUsers = append(c.FTPUsers[:i], c.FTPUsers[i+1:]...)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// UpdateFTPUser updates an existing FTP user
|
||||
func (c *Config) UpdateFTPUser(username string, user FTPUser) bool {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for i, u := range c.FTPUsers {
|
||||
if u.Username == username {
|
||||
c.FTPUsers[i] = user
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AuthenticateAdmin checks admin credentials
|
||||
func (c *Config) AuthenticateAdmin(username, password string) bool {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.Admin.Username == username && c.Admin.Password == password
|
||||
}
|
||||
|
||||
// GetFTPUsers returns a copy of all FTP users
|
||||
func (c *Config) GetFTPUsers() []FTPUser {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
users := make([]FTPUser, len(c.FTPUsers))
|
||||
copy(users, c.FTPUsers)
|
||||
return users
|
||||
}
|
||||
Reference in New Issue
Block a user