mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-21 23:20:24 +00:00
transfer logs: add FTP mode
This commit is contained in:
parent
0de0d3308c
commit
555dc3b0c0
6 changed files with 63 additions and 8 deletions
|
@ -30,6 +30,7 @@ type BaseTransfer struct { //nolint:maligned
|
|||
fsPath string
|
||||
effectiveFsPath string
|
||||
requestPath string
|
||||
ftpMode string
|
||||
start time.Time
|
||||
MaxWriteSize int64
|
||||
MinWriteOffset int64
|
||||
|
@ -68,6 +69,11 @@ func NewBaseTransfer(file vfs.File, conn *BaseConnection, cancelFn func(), fsPat
|
|||
return t
|
||||
}
|
||||
|
||||
// SetFtpMode sets the FTP mode for the current transfer
|
||||
func (t *BaseTransfer) SetFtpMode(mode string) {
|
||||
t.ftpMode = mode
|
||||
}
|
||||
|
||||
// GetID returns the transfer ID
|
||||
func (t *BaseTransfer) GetID() uint64 {
|
||||
return t.ID
|
||||
|
@ -236,7 +242,7 @@ func (t *BaseTransfer) Close() error {
|
|||
elapsed := time.Since(t.start).Nanoseconds() / 1000000
|
||||
if t.transferType == TransferDownload {
|
||||
logger.TransferLog(downloadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesSent), t.Connection.User.Username,
|
||||
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr)
|
||||
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr, t.ftpMode)
|
||||
ExecuteActionNotification(&t.Connection.User, operationDownload, t.fsPath, t.requestPath, "", "", t.Connection.protocol,
|
||||
atomic.LoadInt64(&t.BytesSent), t.ErrTransfer)
|
||||
} else {
|
||||
|
@ -247,7 +253,7 @@ func (t *BaseTransfer) Close() error {
|
|||
t.Connection.Log(logger.LevelDebug, "uploaded file size %v", fileSize)
|
||||
t.updateQuota(numFiles, fileSize)
|
||||
logger.TransferLog(uploadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesReceived), t.Connection.User.Username,
|
||||
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr)
|
||||
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr, t.ftpMode)
|
||||
ExecuteActionNotification(&t.Connection.User, operationUpload, t.fsPath, t.requestPath, "", "", t.Connection.protocol, fileSize,
|
||||
t.ErrTransfer)
|
||||
}
|
||||
|
|
|
@ -284,3 +284,16 @@ func TestRemovePartialCryptoFile(t *testing.T) {
|
|||
assert.Equal(t, int64(9), size)
|
||||
assert.NoFileExists(t, testFile)
|
||||
}
|
||||
|
||||
func TestFTPMode(t *testing.T) {
|
||||
conn := NewBaseConnection("", ProtocolFTP, "", "", dataprovider.User{})
|
||||
transfer := BaseTransfer{
|
||||
Connection: conn,
|
||||
transferType: TransferUpload,
|
||||
BytesReceived: 123,
|
||||
Fs: vfs.NewOsFs("", os.TempDir(), ""),
|
||||
}
|
||||
assert.Empty(t, transfer.ftpMode)
|
||||
transfer.SetFtpMode("active")
|
||||
assert.Equal(t, "active", transfer.ftpMode)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ The logs can be divided into the following categories:
|
|||
- `username`, string
|
||||
- `file_path` string
|
||||
- `connection_id` string. Unique connection identifier
|
||||
- `protocol` string. `SFTP` or `SCP`
|
||||
- `protocol` string. `SFTP`, `SCP`, `SSH`, `FTP`, `HTTP`, `DAV`
|
||||
- `ftp_mode`, string. `active` or `passive`. Included only for `FTP` protocol
|
||||
- **"command logs"**, SFTP/SCP command logs:
|
||||
- `sender` string. `Rename`, `Rmdir`, `Mkdir`, `Symlink`, `Remove`, `Chmod`, `Chown`, `Chtimes`, `Truncate`, `SSHCommand`
|
||||
- `level` string
|
||||
|
|
|
@ -30,6 +30,19 @@ type Connection struct {
|
|||
clientContext ftpserver.ClientContext
|
||||
}
|
||||
|
||||
func (c *Connection) getFTPMode() string {
|
||||
if c.clientContext == nil {
|
||||
return ""
|
||||
}
|
||||
switch c.clientContext.GetLastDataChannel() {
|
||||
case ftpserver.DataChannelActive:
|
||||
return "active"
|
||||
case ftpserver.DataChannelPassive:
|
||||
return "passive"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetClientVersion returns the connected client's version.
|
||||
// It returns "Unknown" if the client does not advertise its
|
||||
// version
|
||||
|
@ -325,6 +338,7 @@ func (c *Connection) downloadFile(fs vfs.Fs, fsPath, ftpPath string, offset int6
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, fsPath, fsPath, ftpPath, common.TransferDownload,
|
||||
0, 0, 0, false, fs)
|
||||
baseTransfer.SetFtpMode(c.getFTPMode())
|
||||
t := newTransfer(baseTransfer, nil, r, offset)
|
||||
|
||||
return t, nil
|
||||
|
@ -390,6 +404,7 @@ func (c *Connection) handleFTPUploadToNewFile(fs vfs.Fs, resolvedPath, filePath,
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, resolvedPath, filePath, requestPath,
|
||||
common.TransferUpload, 0, 0, maxWriteSize, true, fs)
|
||||
baseTransfer.SetFtpMode(c.getFTPMode())
|
||||
t := newTransfer(baseTransfer, w, nil, 0)
|
||||
|
||||
return t, nil
|
||||
|
@ -466,6 +481,7 @@ func (c *Connection) handleFTPUploadToExistingFile(fs vfs.Fs, flags int, resolve
|
|||
|
||||
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, resolvedPath, filePath, requestPath,
|
||||
common.TransferUpload, minWriteOffset, initialSize, maxWriteSize, false, fs)
|
||||
baseTransfer.SetFtpMode(c.getFTPMode())
|
||||
t := newTransfer(baseTransfer, w, nil, 0)
|
||||
|
||||
return t, nil
|
||||
|
|
|
@ -253,6 +253,7 @@ xr5cb9VBRBtB9aOKVfuRhpatAfS2Pzm2Htae9lFn7slGPUmu2hkjDw==
|
|||
)
|
||||
|
||||
type mockFTPClientContext struct {
|
||||
lastDataChannel ftpserver.DataChannel
|
||||
}
|
||||
|
||||
func (cc mockFTPClientContext) Path() string {
|
||||
|
@ -298,7 +299,7 @@ func (cc mockFTPClientContext) GetLastCommand() string {
|
|||
}
|
||||
|
||||
func (cc mockFTPClientContext) GetLastDataChannel() ftpserver.DataChannel {
|
||||
return ftpserver.DataChannelPassive
|
||||
return cc.lastDataChannel
|
||||
}
|
||||
|
||||
// MockOsFs mockable OsFs
|
||||
|
@ -559,6 +560,19 @@ func TestUserInvalidParams(t *testing.T) {
|
|||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestFTPMode(t *testing.T) {
|
||||
connection := &Connection{
|
||||
BaseConnection: common.NewBaseConnection("", common.ProtocolFTP, "", "", dataprovider.User{}),
|
||||
}
|
||||
assert.Empty(t, connection.getFTPMode())
|
||||
connection.clientContext = mockFTPClientContext{lastDataChannel: ftpserver.DataChannelActive}
|
||||
assert.Equal(t, "active", connection.getFTPMode())
|
||||
connection.clientContext = mockFTPClientContext{lastDataChannel: ftpserver.DataChannelPassive}
|
||||
assert.Equal(t, "passive", connection.getFTPMode())
|
||||
connection.clientContext = mockFTPClientContext{lastDataChannel: 0}
|
||||
assert.Empty(t, connection.getFTPMode())
|
||||
}
|
||||
|
||||
func TestClientVersion(t *testing.T) {
|
||||
mockCC := mockFTPClientContext{}
|
||||
connID := fmt.Sprintf("2_%v", mockCC.ID())
|
||||
|
|
|
@ -259,8 +259,10 @@ func ErrorToConsole(format string, v ...interface{}) {
|
|||
}
|
||||
|
||||
// TransferLog logs uploads or downloads
|
||||
func TransferLog(operation, path string, elapsed int64, size int64, user, connectionID, protocol, localAddr, remoteAddr string) {
|
||||
logger.Info().
|
||||
func TransferLog(operation, path string, elapsed int64, size int64, user, connectionID, protocol, localAddr,
|
||||
remoteAddr, ftpMode string,
|
||||
) {
|
||||
ev := logger.Info().
|
||||
Timestamp().
|
||||
Str("sender", operation).
|
||||
Str("local_addr", localAddr).
|
||||
|
@ -270,8 +272,11 @@ func TransferLog(operation, path string, elapsed int64, size int64, user, connec
|
|||
Str("username", user).
|
||||
Str("file_path", path).
|
||||
Str("connection_id", connectionID).
|
||||
Str("protocol", protocol).
|
||||
Send()
|
||||
Str("protocol", protocol)
|
||||
if ftpMode != "" {
|
||||
ev.Str("ftp_mode", ftpMode)
|
||||
}
|
||||
ev.Send()
|
||||
}
|
||||
|
||||
// CommandLog logs an SFTP/SCP/SSH command
|
||||
|
|
Loading…
Reference in a new issue