mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 23:00:55 +03:00
refactoring: add common package
The common package defines the interfaces that a protocol must implement and contain code that can be shared among supported protocols. This way should be easier to support new protocols
This commit is contained in:
@@ -11,9 +11,9 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/dataprovider"
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/vfs"
|
||||
)
|
||||
|
||||
@@ -154,7 +154,7 @@ func restoreFolders(folders []vfs.BaseVirtualFolder, inputFile string, scanQuota
|
||||
return err
|
||||
}
|
||||
if scanQuota >= 1 {
|
||||
if sftpd.AddVFolderQuotaScan(folder.MappedPath) {
|
||||
if common.QuotaScans.AddVFolderQuotaScan(folder.MappedPath) {
|
||||
logger.Debug(logSender, "", "starting quota scan for restored folder: %#v", folder.MappedPath)
|
||||
go doFolderQuotaScan(folder) //nolint:errcheck
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func restoreUsers(users []dataprovider.User, inputFile string, mode, scanQuota i
|
||||
return err
|
||||
}
|
||||
if scanQuota == 1 || (scanQuota == 2 && user.HasQuotaRestrictions()) {
|
||||
if sftpd.AddQuotaScan(user.Username) {
|
||||
if common.QuotaScans.AddUserQuotaScan(user.Username) {
|
||||
logger.Debug(logSender, "", "starting quota scan for restored user: %#v", user.Username)
|
||||
go doQuotaScan(user) //nolint:errcheck
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
|
||||
"github.com/go-chi/render"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/dataprovider"
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/vfs"
|
||||
)
|
||||
|
||||
@@ -18,11 +18,11 @@ const (
|
||||
)
|
||||
|
||||
func getQuotaScans(w http.ResponseWriter, r *http.Request) {
|
||||
render.JSON(w, r, sftpd.GetQuotaScans())
|
||||
render.JSON(w, r, common.QuotaScans.GetUsersQuotaScans())
|
||||
}
|
||||
|
||||
func getVFolderQuotaScans(w http.ResponseWriter, r *http.Request) {
|
||||
render.JSON(w, r, sftpd.GetVFoldersQuotaScans())
|
||||
render.JSON(w, r, common.QuotaScans.GetVFoldersQuotaScans())
|
||||
}
|
||||
|
||||
func updateUserQuotaUsage(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -53,11 +53,11 @@ func updateUserQuotaUsage(w http.ResponseWriter, r *http.Request) {
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !sftpd.AddQuotaScan(user.Username) {
|
||||
if !common.QuotaScans.AddUserQuotaScan(user.Username) {
|
||||
sendAPIResponse(w, r, err, "A quota scan is in progress for this user", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
defer sftpd.RemoveQuotaScan(user.Username) //nolint:errcheck
|
||||
defer common.QuotaScans.RemoveUserQuotaScan(user.Username)
|
||||
err = dataprovider.UpdateUserQuota(user, u.UsedQuotaFiles, u.UsedQuotaSize, mode == quotaUpdateModeReset)
|
||||
if err != nil {
|
||||
sendAPIResponse(w, r, err, "", getRespStatus(err))
|
||||
@@ -89,11 +89,11 @@ func updateVFolderQuotaUsage(w http.ResponseWriter, r *http.Request) {
|
||||
sendAPIResponse(w, r, err, "", getRespStatus(err))
|
||||
return
|
||||
}
|
||||
if !sftpd.AddVFolderQuotaScan(folder.MappedPath) {
|
||||
if !common.QuotaScans.AddVFolderQuotaScan(folder.MappedPath) {
|
||||
sendAPIResponse(w, r, err, "A quota scan is in progress for this folder", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
defer sftpd.RemoveVFolderQuotaScan(folder.MappedPath) //nolint:errcheck
|
||||
defer common.QuotaScans.RemoveVFolderQuotaScan(folder.MappedPath)
|
||||
err = dataprovider.UpdateVirtualFolderQuota(folder, f.UsedQuotaFiles, f.UsedQuotaSize, mode == quotaUpdateModeReset)
|
||||
if err != nil {
|
||||
sendAPIResponse(w, r, err, "", getRespStatus(err))
|
||||
@@ -119,7 +119,7 @@ func startQuotaScan(w http.ResponseWriter, r *http.Request) {
|
||||
sendAPIResponse(w, r, err, "", getRespStatus(err))
|
||||
return
|
||||
}
|
||||
if sftpd.AddQuotaScan(user.Username) {
|
||||
if common.QuotaScans.AddUserQuotaScan(user.Username) {
|
||||
go doQuotaScan(user) //nolint:errcheck
|
||||
sendAPIResponse(w, r, err, "Scan started", http.StatusCreated)
|
||||
} else {
|
||||
@@ -144,7 +144,7 @@ func startVFolderQuotaScan(w http.ResponseWriter, r *http.Request) {
|
||||
sendAPIResponse(w, r, err, "", getRespStatus(err))
|
||||
return
|
||||
}
|
||||
if sftpd.AddVFolderQuotaScan(folder.MappedPath) {
|
||||
if common.QuotaScans.AddVFolderQuotaScan(folder.MappedPath) {
|
||||
go doFolderQuotaScan(folder) //nolint:errcheck
|
||||
sendAPIResponse(w, r, err, "Scan started", http.StatusCreated)
|
||||
} else {
|
||||
@@ -153,7 +153,7 @@ func startVFolderQuotaScan(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func doQuotaScan(user dataprovider.User) error {
|
||||
defer sftpd.RemoveQuotaScan(user.Username) //nolint:errcheck
|
||||
defer common.QuotaScans.RemoveUserQuotaScan(user.Username)
|
||||
fs, err := user.GetFilesystem("")
|
||||
if err != nil {
|
||||
logger.Warn(logSender, "", "unable scan quota for user %#v error creating filesystem: %v", user.Username, err)
|
||||
@@ -170,7 +170,7 @@ func doQuotaScan(user dataprovider.User) error {
|
||||
}
|
||||
|
||||
func doFolderQuotaScan(folder vfs.BaseVirtualFolder) error {
|
||||
defer sftpd.RemoveVFolderQuotaScan(folder.MappedPath) //nolint:errcheck
|
||||
defer common.QuotaScans.RemoveVFolderQuotaScan(folder.MappedPath)
|
||||
fs := vfs.NewOsFs("", "", nil).(vfs.OsFs)
|
||||
numFiles, size, err := fs.GetDirSize(folder.MappedPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
|
||||
"github.com/go-chi/render"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/dataprovider"
|
||||
"github.com/drakkan/sftpgo/httpclient"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/utils"
|
||||
"github.com/drakkan/sftpgo/version"
|
||||
"github.com/drakkan/sftpgo/vfs"
|
||||
@@ -204,8 +204,8 @@ func GetUsers(limit, offset int64, username string, expectedStatusCode int) ([]d
|
||||
}
|
||||
|
||||
// GetQuotaScans gets active quota scans for users and checks the received HTTP Status code against expectedStatusCode.
|
||||
func GetQuotaScans(expectedStatusCode int) ([]sftpd.ActiveQuotaScan, []byte, error) {
|
||||
var quotaScans []sftpd.ActiveQuotaScan
|
||||
func GetQuotaScans(expectedStatusCode int) ([]common.ActiveQuotaScan, []byte, error) {
|
||||
var quotaScans []common.ActiveQuotaScan
|
||||
var body []byte
|
||||
resp, err := sendHTTPRequest(http.MethodGet, buildURLRelativeToBase(quotaScanPath), nil, "")
|
||||
if err != nil {
|
||||
@@ -252,8 +252,8 @@ func UpdateQuotaUsage(user dataprovider.User, mode string, expectedStatusCode in
|
||||
}
|
||||
|
||||
// GetConnections returns status and stats for active SFTP/SCP connections
|
||||
func GetConnections(expectedStatusCode int) ([]sftpd.ConnectionStatus, []byte, error) {
|
||||
var connections []sftpd.ConnectionStatus
|
||||
func GetConnections(expectedStatusCode int) ([]common.ConnectionStatus, []byte, error) {
|
||||
var connections []common.ConnectionStatus
|
||||
var body []byte
|
||||
resp, err := sendHTTPRequest(http.MethodGet, buildURLRelativeToBase(activeConnectionsPath), nil, "")
|
||||
if err != nil {
|
||||
@@ -360,8 +360,8 @@ func GetFolders(limit int64, offset int64, mappedPath string, expectedStatusCode
|
||||
}
|
||||
|
||||
// GetFoldersQuotaScans gets active quota scans for folders and checks the received HTTP Status code against expectedStatusCode.
|
||||
func GetFoldersQuotaScans(expectedStatusCode int) ([]sftpd.ActiveVirtualFolderQuotaScan, []byte, error) {
|
||||
var quotaScans []sftpd.ActiveVirtualFolderQuotaScan
|
||||
func GetFoldersQuotaScans(expectedStatusCode int) ([]common.ActiveVirtualFolderQuotaScan, []byte, error) {
|
||||
var quotaScans []common.ActiveVirtualFolderQuotaScan
|
||||
var body []byte
|
||||
resp, err := sendHTTPRequest(http.MethodGet, buildURLRelativeToBase(quotaScanVFolderPath), nil, "")
|
||||
if err != nil {
|
||||
|
||||
@@ -33,10 +33,10 @@ type httpAuthProvider interface {
|
||||
}
|
||||
|
||||
type basicAuthProvider struct {
|
||||
Path string
|
||||
Path string
|
||||
sync.RWMutex
|
||||
Info os.FileInfo
|
||||
Users map[string]string
|
||||
lock *sync.RWMutex
|
||||
}
|
||||
|
||||
func newBasicAuthProvider(authUserFile string) (httpAuthProvider, error) {
|
||||
@@ -44,7 +44,6 @@ func newBasicAuthProvider(authUserFile string) (httpAuthProvider, error) {
|
||||
Path: authUserFile,
|
||||
Info: nil,
|
||||
Users: make(map[string]string),
|
||||
lock: new(sync.RWMutex),
|
||||
}
|
||||
return &basicAuthProvider, basicAuthProvider.loadUsers()
|
||||
}
|
||||
@@ -54,8 +53,8 @@ func (p *basicAuthProvider) isEnabled() bool {
|
||||
}
|
||||
|
||||
func (p *basicAuthProvider) isReloadNeeded(info os.FileInfo) bool {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
return p.Info == nil || p.Info.ModTime() != info.ModTime() || p.Info.Size() != info.Size()
|
||||
}
|
||||
|
||||
@@ -84,8 +83,8 @@ func (p *basicAuthProvider) loadUsers() error {
|
||||
logger.Debug(logSender, "", "unable to parse basic auth users file: %v", err)
|
||||
return err
|
||||
}
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
p.Users = make(map[string]string)
|
||||
for _, record := range records {
|
||||
if len(record) == 2 {
|
||||
@@ -103,8 +102,8 @@ func (p *basicAuthProvider) getHashedPassword(username string) (string, bool) {
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
pwd, ok := p.Users[username]
|
||||
return pwd, ok
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/utils"
|
||||
)
|
||||
@@ -50,7 +51,7 @@ var (
|
||||
router *chi.Mux
|
||||
backupsPath string
|
||||
httpAuth httpAuthProvider
|
||||
certMgr *certManager
|
||||
certMgr *common.CertManager
|
||||
)
|
||||
|
||||
// Conf httpd daemon configuration
|
||||
@@ -123,7 +124,7 @@ func (c Conf) Initialize(configDir string, enableProfiler bool) error {
|
||||
MaxHeaderBytes: 1 << 16, // 64KB
|
||||
}
|
||||
if len(certificateFile) > 0 && len(certificateKeyFile) > 0 {
|
||||
certMgr, err = newCertManager(certificateFile, certificateKeyFile)
|
||||
certMgr, err = common.NewCertManager(certificateFile, certificateKeyFile, logSender)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -139,7 +140,7 @@ func (c Conf) Initialize(configDir string, enableProfiler bool) error {
|
||||
// ReloadTLSCertificate reloads the TLS certificate and key from the configured paths
|
||||
func ReloadTLSCertificate() error {
|
||||
if certMgr != nil {
|
||||
return certMgr.loadCertificate()
|
||||
return certMgr.LoadCertificate(logSender)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -28,11 +28,11 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/config"
|
||||
"github.com/drakkan/sftpgo/dataprovider"
|
||||
"github.com/drakkan/sftpgo/httpd"
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/utils"
|
||||
"github.com/drakkan/sftpgo/vfs"
|
||||
)
|
||||
@@ -41,7 +41,6 @@ const (
|
||||
defaultUsername = "test_user"
|
||||
defaultPassword = "test_password"
|
||||
testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
|
||||
logSender = "APITesting"
|
||||
userPath = "/api/v1/user"
|
||||
folderPath = "/api/v1/folder"
|
||||
activeConnectionsPath = "/api/v1/connection"
|
||||
@@ -109,6 +108,8 @@ func TestMain(m *testing.M) {
|
||||
os.RemoveAll(credentialsPath) //nolint:errcheck
|
||||
logger.InfoToConsole("Starting HTTPD tests, provider: %v", providerConf.Driver)
|
||||
|
||||
common.Initialize(config.GetCommonConfig())
|
||||
|
||||
err = dataprovider.Initialize(providerConf, configDir)
|
||||
if err != nil {
|
||||
logger.WarnToConsole("error initializing data provider: %v", err)
|
||||
@@ -126,13 +127,14 @@ func TestMain(m *testing.M) {
|
||||
httpdConf.BackupsPath = backupsPath
|
||||
err = os.MkdirAll(backupsPath, os.ModePerm)
|
||||
if err != nil {
|
||||
logger.WarnToConsole("error creating backups path: %v", err)
|
||||
logger.ErrorToConsole("error creating backups path: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := httpdConf.Initialize(configDir, true); err != nil {
|
||||
logger.ErrorToConsole("could not start HTTP server: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -140,14 +142,14 @@ func TestMain(m *testing.M) {
|
||||
// now start an https server
|
||||
certPath := filepath.Join(os.TempDir(), "test.crt")
|
||||
keyPath := filepath.Join(os.TempDir(), "test.key")
|
||||
err = ioutil.WriteFile(certPath, []byte(httpsCert), 0666)
|
||||
err = ioutil.WriteFile(certPath, []byte(httpsCert), os.ModePerm)
|
||||
if err != nil {
|
||||
logger.WarnToConsole("error writing HTTPS certificate: %v", err)
|
||||
logger.ErrorToConsole("error writing HTTPS certificate: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = ioutil.WriteFile(keyPath, []byte(httpsKey), 0666)
|
||||
err = ioutil.WriteFile(keyPath, []byte(httpsKey), os.ModePerm)
|
||||
if err != nil {
|
||||
logger.WarnToConsole("error writing HTTPS private key: %v", err)
|
||||
logger.ErrorToConsole("error writing HTTPS private key: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
httpdConf.BindPort = 8443
|
||||
@@ -156,7 +158,8 @@ func TestMain(m *testing.M) {
|
||||
|
||||
go func() {
|
||||
if err := httpdConf.Initialize(configDir, true); err != nil {
|
||||
logger.Error(logSender, "", "could not start HTTPS server: %v", err)
|
||||
logger.ErrorToConsole("could not start HTTPS server: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
|
||||
@@ -1673,11 +1676,11 @@ func TestUpdateUserQuotaUsageMock(t *testing.T) {
|
||||
req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath, bytes.NewBuffer([]byte("string")))
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusBadRequest, rr.Code)
|
||||
assert.True(t, sftpd.AddQuotaScan(user.Username))
|
||||
assert.True(t, common.QuotaScans.AddUserQuotaScan(user.Username))
|
||||
req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath, bytes.NewBuffer(userAsJSON))
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusConflict, rr.Code)
|
||||
assert.NoError(t, sftpd.RemoveQuotaScan(user.Username))
|
||||
assert.True(t, common.QuotaScans.RemoveUserQuotaScan(user.Username))
|
||||
req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, rr.Code)
|
||||
@@ -1854,12 +1857,11 @@ func TestStartQuotaScanMock(t *testing.T) {
|
||||
}
|
||||
// simulate a duplicate quota scan
|
||||
userAsJSON = getUserAsJSON(t, user)
|
||||
sftpd.AddQuotaScan(user.Username)
|
||||
common.QuotaScans.AddUserQuotaScan(user.Username)
|
||||
req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusConflict, rr.Code)
|
||||
err = sftpd.RemoveQuotaScan(user.Username)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, common.QuotaScans.RemoveUserQuotaScan(user.Username))
|
||||
|
||||
userAsJSON = getUserAsJSON(t, user)
|
||||
req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
|
||||
@@ -1867,7 +1869,7 @@ func TestStartQuotaScanMock(t *testing.T) {
|
||||
checkResponseCode(t, http.StatusCreated, rr.Code)
|
||||
|
||||
for {
|
||||
var scans []sftpd.ActiveQuotaScan
|
||||
var scans []common.ActiveQuotaScan
|
||||
req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, rr.Code)
|
||||
@@ -1890,7 +1892,7 @@ func TestStartQuotaScanMock(t *testing.T) {
|
||||
checkResponseCode(t, http.StatusCreated, rr.Code)
|
||||
|
||||
for {
|
||||
var scans []sftpd.ActiveQuotaScan
|
||||
var scans []common.ActiveQuotaScan
|
||||
req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, rr.Code)
|
||||
@@ -1954,11 +1956,11 @@ func TestUpdateFolderQuotaUsageMock(t *testing.T) {
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusBadRequest, rr.Code)
|
||||
|
||||
assert.True(t, sftpd.AddVFolderQuotaScan(mappedPath))
|
||||
assert.True(t, common.QuotaScans.AddVFolderQuotaScan(mappedPath))
|
||||
req, _ = http.NewRequest(http.MethodPut, updateFolderUsedQuotaPath, bytes.NewBuffer(folderAsJSON))
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusConflict, rr.Code)
|
||||
assert.NoError(t, sftpd.RemoveVFolderQuotaScan(mappedPath))
|
||||
assert.True(t, common.QuotaScans.RemoveVFolderQuotaScan(mappedPath))
|
||||
|
||||
url, err = url.Parse(folderPath)
|
||||
assert.NoError(t, err)
|
||||
@@ -1986,12 +1988,11 @@ func TestStartFolderQuotaScanMock(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
// simulate a duplicate quota scan
|
||||
sftpd.AddVFolderQuotaScan(mappedPath)
|
||||
common.QuotaScans.AddVFolderQuotaScan(mappedPath)
|
||||
req, _ = http.NewRequest(http.MethodPost, quotaScanVFolderPath, bytes.NewBuffer(folderAsJSON))
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusConflict, rr.Code)
|
||||
err = sftpd.RemoveVFolderQuotaScan(mappedPath)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, common.QuotaScans.RemoveVFolderQuotaScan(mappedPath))
|
||||
// and now a real quota scan
|
||||
_, err = os.Stat(mappedPath)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
@@ -2001,7 +2002,7 @@ func TestStartFolderQuotaScanMock(t *testing.T) {
|
||||
req, _ = http.NewRequest(http.MethodPost, quotaScanVFolderPath, bytes.NewBuffer(folderAsJSON))
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusCreated, rr.Code)
|
||||
var scans []sftpd.ActiveVirtualFolderQuotaScan
|
||||
var scans []common.ActiveVirtualFolderQuotaScan
|
||||
for {
|
||||
req, _ = http.NewRequest(http.MethodGet, quotaScanVFolderPath, nil)
|
||||
rr = executeRequest(req)
|
||||
@@ -2772,7 +2773,7 @@ func waitTCPListening(address string) {
|
||||
continue
|
||||
}
|
||||
logger.InfoToConsole("tcp server %v now listening\n", address)
|
||||
defer conn.Close()
|
||||
conn.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/dataprovider"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/utils"
|
||||
"github.com/drakkan/sftpgo/vfs"
|
||||
)
|
||||
@@ -526,7 +526,7 @@ func TestQuotaScanInvalidFs(t *testing.T) {
|
||||
Provider: 1,
|
||||
},
|
||||
}
|
||||
sftpd.AddQuotaScan(user.Username)
|
||||
common.QuotaScans.AddUserQuotaScan(user.Username)
|
||||
err := doQuotaScan(user)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/render"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/dataprovider"
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
"github.com/drakkan/sftpgo/metrics"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/version"
|
||||
)
|
||||
|
||||
@@ -68,7 +68,7 @@ func initializeRouter(staticFilesPath string, enableProfiler, enableWebAdmin boo
|
||||
})
|
||||
|
||||
router.Get(activeConnectionsPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
render.JSON(w, r, sftpd.GetConnectionsStats())
|
||||
render.JSON(w, r, common.Connections.GetStats())
|
||||
})
|
||||
|
||||
router.Delete(activeConnectionsPath+"/{connectionID}", handleCloseConnection)
|
||||
@@ -116,7 +116,7 @@ func handleCloseConnection(w http.ResponseWriter, r *http.Request) {
|
||||
sendAPIResponse(w, r, nil, "connectionID is mandatory", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if sftpd.CloseActiveConnection(connectionID) {
|
||||
if common.Connections.Close(connectionID) {
|
||||
sendAPIResponse(w, r, nil, "Connection closed", http.StatusOK)
|
||||
} else {
|
||||
sendAPIResponse(w, r, nil, "Not Found", http.StatusNotFound)
|
||||
|
||||
@@ -2,7 +2,7 @@ openapi: 3.0.1
|
||||
info:
|
||||
title: SFTPGo
|
||||
description: 'SFTPGo REST API'
|
||||
version: 1.9.1
|
||||
version: 1.9.2
|
||||
|
||||
servers:
|
||||
- url: /api/v1
|
||||
@@ -1778,10 +1778,6 @@ components:
|
||||
type: integer
|
||||
format: int64
|
||||
description: bytes transferred
|
||||
last_activity:
|
||||
type: integer
|
||||
format: int64
|
||||
description: last transfer activity as unix timestamp in milliseconds
|
||||
ConnectionStatus:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1793,6 +1789,7 @@ components:
|
||||
description: unique connection identifier
|
||||
client_version:
|
||||
type: string
|
||||
nullable: true
|
||||
description: client version
|
||||
remote_address:
|
||||
type: string
|
||||
@@ -1803,6 +1800,7 @@ components:
|
||||
description: connection time as unix timestamp in milliseconds
|
||||
ssh_command:
|
||||
type: string
|
||||
nullable: true
|
||||
description: SSH command. This is not empty for protocol SSH
|
||||
last_activity:
|
||||
type: integer
|
||||
@@ -1816,6 +1814,7 @@ components:
|
||||
- SSH
|
||||
active_transfers:
|
||||
type: array
|
||||
nullable: true
|
||||
items:
|
||||
$ref : '#/components/schemas/Transfer'
|
||||
QuotaScan:
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package httpd
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"sync"
|
||||
|
||||
"github.com/drakkan/sftpgo/logger"
|
||||
)
|
||||
|
||||
type certManager struct {
|
||||
cert *tls.Certificate
|
||||
certPath string
|
||||
keyPath string
|
||||
lock *sync.RWMutex
|
||||
}
|
||||
|
||||
func (m *certManager) loadCertificate() error {
|
||||
newCert, err := tls.LoadX509KeyPair(m.certPath, m.keyPath)
|
||||
if err != nil {
|
||||
logger.Warn(logSender, "", "unable to load https certificate: %v", err)
|
||||
return err
|
||||
}
|
||||
logger.Debug(logSender, "", "https certificate successfully loaded")
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
m.cert = &newCert
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *certManager) GetCertificateFunc() func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
return func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
return m.cert, nil
|
||||
}
|
||||
}
|
||||
|
||||
func newCertManager(certificateFile, certificateKeyFile string) (*certManager, error) {
|
||||
manager := &certManager{
|
||||
cert: nil,
|
||||
certPath: certificateFile,
|
||||
keyPath: certificateKeyFile,
|
||||
lock: new(sync.RWMutex),
|
||||
}
|
||||
err := manager.loadCertificate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return manager, nil
|
||||
}
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
|
||||
"github.com/drakkan/sftpgo/common"
|
||||
"github.com/drakkan/sftpgo/dataprovider"
|
||||
"github.com/drakkan/sftpgo/sftpd"
|
||||
"github.com/drakkan/sftpgo/utils"
|
||||
"github.com/drakkan/sftpgo/version"
|
||||
"github.com/drakkan/sftpgo/vfs"
|
||||
@@ -77,7 +77,7 @@ type foldersPage struct {
|
||||
|
||||
type connectionsPage struct {
|
||||
basePage
|
||||
Connections []sftpd.ConnectionStatus
|
||||
Connections []common.ConnectionStatus
|
||||
}
|
||||
|
||||
type userPage struct {
|
||||
@@ -603,7 +603,7 @@ func handleWebUpdateUserPost(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func handleWebGetConnections(w http.ResponseWriter, r *http.Request) {
|
||||
connectionStats := sftpd.GetConnectionsStats()
|
||||
connectionStats := common.Connections.GetStats()
|
||||
data := connectionsPage{
|
||||
basePage: getBasePageData(pageConnectionsTitle, webConnectionsPath),
|
||||
Connections: connectionStats,
|
||||
|
||||
Reference in New Issue
Block a user