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:
Nicola Murino
2020-07-24 23:39:38 +02:00
parent ded8fad5e4
commit 4e41a5583d
62 changed files with 4893 additions and 3140 deletions

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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:

View File

@@ -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
}

View File

@@ -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,