mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-21 15:10:23 +00:00
EventManager: add datetime placeholder
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
0c470b9202
commit
4103344989
12 changed files with 70 additions and 29 deletions
|
@ -673,7 +673,7 @@ func (c *Configuration) notifyCertificateRenewal(domain string, err error) {
|
||||||
params := common.EventParams{
|
params := common.EventParams{
|
||||||
Name: domain,
|
Name: domain,
|
||||||
Event: "Certificate renewal",
|
Event: "Certificate renewal",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
params.Status = 2
|
params.Status = 2
|
||||||
|
|
|
@ -92,8 +92,9 @@ func ExecutePreAction(conn *BaseConnection, operation, filePath, virtualPath str
|
||||||
if !hasHook && !hasNotifiersPlugin && !hasRules {
|
if !hasHook && !hasNotifiersPlugin && !hasRules {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
dateTime := time.Now()
|
||||||
event = newActionNotification(&conn.User, operation, filePath, virtualPath, "", "", "",
|
event = newActionNotification(&conn.User, operation, filePath, virtualPath, "", "", "",
|
||||||
conn.protocol, conn.GetRemoteIP(), conn.ID, fileSize, openFlags, conn.getNotificationStatus(nil), 0, nil)
|
conn.protocol, conn.GetRemoteIP(), conn.ID, fileSize, openFlags, conn.getNotificationStatus(nil), 0, dateTime, nil)
|
||||||
if hasNotifiersPlugin {
|
if hasNotifiersPlugin {
|
||||||
plugin.Handler.NotifyFsEvent(event)
|
plugin.Handler.NotifyFsEvent(event)
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ func ExecutePreAction(conn *BaseConnection, operation, filePath, virtualPath str
|
||||||
Protocol: event.Protocol,
|
Protocol: event.Protocol,
|
||||||
IP: event.IP,
|
IP: event.IP,
|
||||||
Role: event.Role,
|
Role: event.Role,
|
||||||
Timestamp: event.Timestamp,
|
Timestamp: dateTime,
|
||||||
Email: conn.User.Email,
|
Email: conn.User.Email,
|
||||||
Object: nil,
|
Object: nil,
|
||||||
}
|
}
|
||||||
|
@ -138,8 +139,9 @@ func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtua
|
||||||
if !hasHook && !hasNotifiersPlugin && !hasRules {
|
if !hasHook && !hasNotifiersPlugin && !hasRules {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
dateTime := time.Now()
|
||||||
notification := newActionNotification(&conn.User, operation, filePath, virtualPath, target, virtualTarget, sshCmd,
|
notification := newActionNotification(&conn.User, operation, filePath, virtualPath, target, virtualTarget, sshCmd,
|
||||||
conn.protocol, conn.GetRemoteIP(), conn.ID, fileSize, 0, conn.getNotificationStatus(err), elapsed, metadata)
|
conn.protocol, conn.GetRemoteIP(), conn.ID, fileSize, 0, conn.getNotificationStatus(err), elapsed, dateTime, metadata)
|
||||||
if hasNotifiersPlugin {
|
if hasNotifiersPlugin {
|
||||||
plugin.Handler.NotifyFsEvent(notification)
|
plugin.Handler.NotifyFsEvent(notification)
|
||||||
}
|
}
|
||||||
|
@ -160,7 +162,7 @@ func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtua
|
||||||
Protocol: notification.Protocol,
|
Protocol: notification.Protocol,
|
||||||
IP: notification.IP,
|
IP: notification.IP,
|
||||||
Role: notification.Role,
|
Role: notification.Role,
|
||||||
Timestamp: notification.Timestamp,
|
Timestamp: dateTime,
|
||||||
Email: conn.User.Email,
|
Email: conn.User.Email,
|
||||||
Object: nil,
|
Object: nil,
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
|
@ -198,6 +200,7 @@ func newActionNotification(
|
||||||
operation, filePath, virtualPath, target, virtualTarget, sshCmd, protocol, ip, sessionID string,
|
operation, filePath, virtualPath, target, virtualTarget, sshCmd, protocol, ip, sessionID string,
|
||||||
fileSize int64,
|
fileSize int64,
|
||||||
openFlags, status int, elapsed int64,
|
openFlags, status int, elapsed int64,
|
||||||
|
datetime time.Time,
|
||||||
metadata map[string]string,
|
metadata map[string]string,
|
||||||
) *notifier.FsEvent {
|
) *notifier.FsEvent {
|
||||||
var bucket, endpoint string
|
var bucket, endpoint string
|
||||||
|
@ -239,7 +242,7 @@ func newActionNotification(
|
||||||
SessionID: sessionID,
|
SessionID: sessionID,
|
||||||
OpenFlags: openFlags,
|
OpenFlags: openFlags,
|
||||||
Role: user.Role,
|
Role: user.Role,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: datetime.UnixNano(),
|
||||||
Elapsed: elapsed,
|
Elapsed: elapsed,
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/lithammer/shortuuid/v4"
|
"github.com/lithammer/shortuuid/v4"
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
|
@ -71,7 +72,7 @@ func TestNewActionNotification(t *testing.T) {
|
||||||
c := NewBaseConnection("id", ProtocolSSH, "", "", user)
|
c := NewBaseConnection("id", ProtocolSSH, "", "", user)
|
||||||
sessionID := xid.New().String()
|
sessionID := xid.New().String()
|
||||||
a := newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
|
a := newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
|
||||||
123, 0, c.getNotificationStatus(errors.New("fake error")), 0, nil)
|
123, 0, c.getNotificationStatus(errors.New("fake error")), 0, time.Now(), nil)
|
||||||
assert.Equal(t, user.Username, a.Username)
|
assert.Equal(t, user.Username, a.Username)
|
||||||
assert.Equal(t, 0, len(a.Bucket))
|
assert.Equal(t, 0, len(a.Bucket))
|
||||||
assert.Equal(t, 0, len(a.Endpoint))
|
assert.Equal(t, 0, len(a.Endpoint))
|
||||||
|
@ -79,38 +80,38 @@ func TestNewActionNotification(t *testing.T) {
|
||||||
|
|
||||||
user.FsConfig.Provider = sdk.S3FilesystemProvider
|
user.FsConfig.Provider = sdk.S3FilesystemProvider
|
||||||
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", sessionID,
|
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", sessionID,
|
||||||
123, 0, c.getNotificationStatus(nil), 0, nil)
|
123, 0, c.getNotificationStatus(nil), 0, time.Now(), nil)
|
||||||
assert.Equal(t, "s3bucket", a.Bucket)
|
assert.Equal(t, "s3bucket", a.Bucket)
|
||||||
assert.Equal(t, "endpoint", a.Endpoint)
|
assert.Equal(t, "endpoint", a.Endpoint)
|
||||||
assert.Equal(t, 1, a.Status)
|
assert.Equal(t, 1, a.Status)
|
||||||
|
|
||||||
user.FsConfig.Provider = sdk.GCSFilesystemProvider
|
user.FsConfig.Provider = sdk.GCSFilesystemProvider
|
||||||
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
||||||
123, 0, c.getNotificationStatus(ErrQuotaExceeded), 0, nil)
|
123, 0, c.getNotificationStatus(ErrQuotaExceeded), 0, time.Now(), nil)
|
||||||
assert.Equal(t, "gcsbucket", a.Bucket)
|
assert.Equal(t, "gcsbucket", a.Bucket)
|
||||||
assert.Equal(t, 0, len(a.Endpoint))
|
assert.Equal(t, 0, len(a.Endpoint))
|
||||||
assert.Equal(t, 3, a.Status)
|
assert.Equal(t, 3, a.Status)
|
||||||
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
||||||
123, 0, c.getNotificationStatus(fmt.Errorf("wrapper quota error: %w", ErrQuotaExceeded)), 0, nil)
|
123, 0, c.getNotificationStatus(fmt.Errorf("wrapper quota error: %w", ErrQuotaExceeded)), 0, time.Now(), nil)
|
||||||
assert.Equal(t, "gcsbucket", a.Bucket)
|
assert.Equal(t, "gcsbucket", a.Bucket)
|
||||||
assert.Equal(t, 0, len(a.Endpoint))
|
assert.Equal(t, 0, len(a.Endpoint))
|
||||||
assert.Equal(t, 3, a.Status)
|
assert.Equal(t, 3, a.Status)
|
||||||
|
|
||||||
user.FsConfig.Provider = sdk.HTTPFilesystemProvider
|
user.FsConfig.Provider = sdk.HTTPFilesystemProvider
|
||||||
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", sessionID,
|
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", sessionID,
|
||||||
123, 0, c.getNotificationStatus(nil), 0, nil)
|
123, 0, c.getNotificationStatus(nil), 0, time.Now(), nil)
|
||||||
assert.Equal(t, "httpendpoint", a.Endpoint)
|
assert.Equal(t, "httpendpoint", a.Endpoint)
|
||||||
assert.Equal(t, 1, a.Status)
|
assert.Equal(t, 1, a.Status)
|
||||||
|
|
||||||
user.FsConfig.Provider = sdk.AzureBlobFilesystemProvider
|
user.FsConfig.Provider = sdk.AzureBlobFilesystemProvider
|
||||||
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
||||||
123, 0, c.getNotificationStatus(nil), 0, nil)
|
123, 0, c.getNotificationStatus(nil), 0, time.Now(), nil)
|
||||||
assert.Equal(t, "azcontainer", a.Bucket)
|
assert.Equal(t, "azcontainer", a.Bucket)
|
||||||
assert.Equal(t, "azendpoint", a.Endpoint)
|
assert.Equal(t, "azendpoint", a.Endpoint)
|
||||||
assert.Equal(t, 1, a.Status)
|
assert.Equal(t, 1, a.Status)
|
||||||
|
|
||||||
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
|
||||||
123, os.O_APPEND, c.getNotificationStatus(nil), 0, nil)
|
123, os.O_APPEND, c.getNotificationStatus(nil), 0, time.Now(), nil)
|
||||||
assert.Equal(t, "azcontainer", a.Bucket)
|
assert.Equal(t, "azcontainer", a.Bucket)
|
||||||
assert.Equal(t, "azendpoint", a.Endpoint)
|
assert.Equal(t, "azendpoint", a.Endpoint)
|
||||||
assert.Equal(t, 1, a.Status)
|
assert.Equal(t, 1, a.Status)
|
||||||
|
@ -118,7 +119,7 @@ func TestNewActionNotification(t *testing.T) {
|
||||||
|
|
||||||
user.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
user.FsConfig.Provider = sdk.SFTPFilesystemProvider
|
||||||
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
|
a = newActionNotification(&user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
|
||||||
123, 0, c.getNotificationStatus(nil), 0, nil)
|
123, 0, c.getNotificationStatus(nil), 0, time.Now(), nil)
|
||||||
assert.Equal(t, "sftpendpoint", a.Endpoint)
|
assert.Equal(t, "sftpendpoint", a.Endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +136,7 @@ func TestActionHTTP(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "",
|
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "",
|
||||||
xid.New().String(), 123, 0, 1, 0, nil)
|
xid.New().String(), 123, 0, 1, 0, time.Now(), nil)
|
||||||
status, err := actionHandler.Handle(a)
|
status, err := actionHandler.Handle(a)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 1, status)
|
assert.Equal(t, 1, status)
|
||||||
|
@ -175,7 +176,7 @@ func TestActionCMD(t *testing.T) {
|
||||||
}
|
}
|
||||||
sessionID := shortuuid.New()
|
sessionID := shortuuid.New()
|
||||||
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
|
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
|
||||||
123, 0, 1, 0, map[string]string{"key": "value"})
|
123, 0, 1, 0, time.Now(), map[string]string{"key": "value"})
|
||||||
status, err := actionHandler.Handle(a)
|
status, err := actionHandler.Handle(a)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 1, status)
|
assert.Equal(t, 1, status)
|
||||||
|
@ -208,7 +209,7 @@ func TestWrongActions(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
a := newActionNotification(user, operationUpload, "", "", "", "", "", ProtocolSFTP, "", xid.New().String(),
|
a := newActionNotification(user, operationUpload, "", "", "", "", "", ProtocolSFTP, "", xid.New().String(),
|
||||||
123, 0, 1, 0, nil)
|
123, 0, 1, 0, time.Now(), nil)
|
||||||
status, err := actionHandler.Handle(a)
|
status, err := actionHandler.Handle(a)
|
||||||
assert.Error(t, err, "action with bad command must fail")
|
assert.Error(t, err, "action with bad command must fail")
|
||||||
assert.Equal(t, 1, status)
|
assert.Equal(t, 1, status)
|
||||||
|
|
|
@ -110,7 +110,7 @@ func (d *dbDefender) AddEvent(ip, protocol string, event HostEvent) bool {
|
||||||
eventManager.handleIPBlockedEvent(EventParams{
|
eventManager.handleIPBlockedEvent(EventParams{
|
||||||
Event: ipBlockedEventName,
|
Event: ipBlockedEventName,
|
||||||
IP: ip,
|
IP: ip,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ func (d *memoryDefender) AddEvent(ip, protocol string, event HostEvent) bool {
|
||||||
eventManager.handleIPBlockedEvent(EventParams{
|
eventManager.handleIPBlockedEvent(EventParams{
|
||||||
Event: ipBlockedEventName,
|
Event: ipBlockedEventName,
|
||||||
IP: ip,
|
IP: ip,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -58,6 +58,7 @@ const (
|
||||||
maxAttachmentsSize = int64(10 * 1024 * 1024)
|
maxAttachmentsSize = int64(10 * 1024 * 1024)
|
||||||
objDataPlaceholder = "{{ObjectData}}"
|
objDataPlaceholder = "{{ObjectData}}"
|
||||||
objDataPlaceholderString = "{{ObjectDataString}}"
|
objDataPlaceholderString = "{{ObjectDataString}}"
|
||||||
|
dateTimeMillisFormat = "2006-01-02T15:04:05.000"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Supported IDP login events
|
// Supported IDP login events
|
||||||
|
@ -89,7 +90,7 @@ func init() {
|
||||||
ObjectType: objectType,
|
ObjectType: objectType,
|
||||||
IP: ip,
|
IP: ip,
|
||||||
Role: role,
|
Role: role,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
Object: object,
|
Object: object,
|
||||||
}
|
}
|
||||||
if u, ok := object.(*dataprovider.User); ok {
|
if u, ok := object.(*dataprovider.User); ok {
|
||||||
|
@ -557,7 +558,7 @@ type EventParams struct {
|
||||||
IP string
|
IP string
|
||||||
Role string
|
Role string
|
||||||
Email string
|
Email string
|
||||||
Timestamp int64
|
Timestamp time.Time
|
||||||
UID string
|
UID string
|
||||||
IDPCustomFields *map[string]string
|
IDPCustomFields *map[string]string
|
||||||
Object plugin.Renderer
|
Object plugin.Renderer
|
||||||
|
@ -641,7 +642,7 @@ func (p *EventParams) setBackupParams(backupPath string) {
|
||||||
p.FsPath = backupPath
|
p.FsPath = backupPath
|
||||||
p.ObjectName = filepath.Base(backupPath)
|
p.ObjectName = filepath.Base(backupPath)
|
||||||
p.VirtualPath = "/" + p.ObjectName
|
p.VirtualPath = "/" + p.ObjectName
|
||||||
p.Timestamp = time.Now().UnixNano()
|
p.Timestamp = time.Now()
|
||||||
info, err := os.Stat(backupPath)
|
info, err := os.Stat(backupPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
p.FileSize = info.Size()
|
p.FileSize = info.Size()
|
||||||
|
@ -775,6 +776,12 @@ func (*EventParams) getStringReplacement(val string, jsonEscaped bool) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []string {
|
func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []string {
|
||||||
|
var dateTimeString string
|
||||||
|
if Config.TZ == "local" {
|
||||||
|
dateTimeString = p.Timestamp.Local().Format(dateTimeMillisFormat)
|
||||||
|
} else {
|
||||||
|
dateTimeString = p.Timestamp.UTC().Format(dateTimeMillisFormat)
|
||||||
|
}
|
||||||
replacements := []string{
|
replacements := []string{
|
||||||
"{{Name}}", p.getStringReplacement(p.Name, jsonEscaped),
|
"{{Name}}", p.getStringReplacement(p.Name, jsonEscaped),
|
||||||
"{{Event}}", p.Event,
|
"{{Event}}", p.Event,
|
||||||
|
@ -791,7 +798,8 @@ func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []s
|
||||||
"{{IP}}", p.IP,
|
"{{IP}}", p.IP,
|
||||||
"{{Role}}", p.getStringReplacement(p.Role, jsonEscaped),
|
"{{Role}}", p.getStringReplacement(p.Role, jsonEscaped),
|
||||||
"{{Email}}", p.getStringReplacement(p.Email, jsonEscaped),
|
"{{Email}}", p.getStringReplacement(p.Email, jsonEscaped),
|
||||||
"{{Timestamp}}", strconv.FormatInt(p.Timestamp, 10),
|
"{{Timestamp}}", strconv.FormatInt(p.Timestamp.UnixNano(), 10),
|
||||||
|
"{{DateTime}}", dateTimeString,
|
||||||
"{{StatusString}}", p.getStatusString(),
|
"{{StatusString}}", p.getStatusString(),
|
||||||
"{{UID}}", p.getStringReplacement(p.UID, jsonEscaped),
|
"{{UID}}", p.getStringReplacement(p.UID, jsonEscaped),
|
||||||
"{{Ext}}", p.getStringReplacement(p.Extension, jsonEscaped),
|
"{{Ext}}", p.getStringReplacement(p.Extension, jsonEscaped),
|
||||||
|
|
|
@ -800,6 +800,28 @@ func TestEventManagerErrors(t *testing.T) {
|
||||||
stopEventScheduler()
|
stopEventScheduler()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDateTimePlaceholder(t *testing.T) {
|
||||||
|
oldTZ := Config.TZ
|
||||||
|
|
||||||
|
Config.TZ = ""
|
||||||
|
dateTime := time.Now()
|
||||||
|
params := EventParams{
|
||||||
|
Timestamp: dateTime,
|
||||||
|
}
|
||||||
|
replacements := params.getStringReplacements(false, false)
|
||||||
|
r := strings.NewReplacer(replacements...)
|
||||||
|
res := r.Replace("{{DateTime}}")
|
||||||
|
assert.Equal(t, dateTime.UTC().Format(dateTimeMillisFormat), res)
|
||||||
|
|
||||||
|
Config.TZ = "local"
|
||||||
|
replacements = params.getStringReplacements(false, false)
|
||||||
|
r = strings.NewReplacer(replacements...)
|
||||||
|
res = r.Replace("{{DateTime}}")
|
||||||
|
assert.Equal(t, dateTime.Local().Format(dateTimeMillisFormat), res)
|
||||||
|
|
||||||
|
Config.TZ = oldTZ
|
||||||
|
}
|
||||||
|
|
||||||
func TestEventRuleActions(t *testing.T) {
|
func TestEventRuleActions(t *testing.T) {
|
||||||
actionName := "test rule action"
|
actionName := "test rule action"
|
||||||
action := dataprovider.BaseEventAction{
|
action := dataprovider.BaseEventAction{
|
||||||
|
|
|
@ -5431,7 +5431,7 @@ func TestBackupAsAttachment(t *testing.T) {
|
||||||
|
|
||||||
common.HandleCertificateEvent(common.EventParams{
|
common.HandleCertificateEvent(common.EventParams{
|
||||||
Name: "example.com",
|
Name: "example.com",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
Event: renewalEvent,
|
Event: renewalEvent,
|
||||||
})
|
})
|
||||||
|
@ -7108,7 +7108,7 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
Recipients: []string{"test@example.com"},
|
Recipients: []string{"test@example.com"},
|
||||||
Subject: `"{{Event}} {{StatusString}}"`,
|
Subject: `"{{Event}} {{StatusString}}"`,
|
||||||
ContentType: 0,
|
ContentType: 0,
|
||||||
Body: "Domain: {{Name}} Timestamp: {{Timestamp}} {{ErrorString}}",
|
Body: "Domain: {{Name}} Timestamp: {{Timestamp}} {{ErrorString}} Date time: {{DateTime}}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7163,7 +7163,7 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
|
|
||||||
common.HandleCertificateEvent(common.EventParams{
|
common.HandleCertificateEvent(common.EventParams{
|
||||||
Name: "example.com",
|
Name: "example.com",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
Event: renewalEvent,
|
Event: renewalEvent,
|
||||||
})
|
})
|
||||||
|
@ -7178,9 +7178,10 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
|
assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
|
||||||
|
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
|
dateTime := time.Now()
|
||||||
params := common.EventParams{
|
params := common.EventParams{
|
||||||
Name: "example.com",
|
Name: "example.com",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: dateTime,
|
||||||
Status: 2,
|
Status: 2,
|
||||||
Event: renewalEvent,
|
Event: renewalEvent,
|
||||||
}
|
}
|
||||||
|
@ -7195,6 +7196,7 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
assert.True(t, slices.Contains(email.To, "test@example.com"))
|
assert.True(t, slices.Contains(email.To, "test@example.com"))
|
||||||
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "%s KO"`, renewalEvent))
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "%s KO"`, renewalEvent))
|
||||||
assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
|
assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
|
||||||
|
assert.Contains(t, email.Data, dateTime.UTC().Format("2006-01-02T15:04:05.000"))
|
||||||
assert.Contains(t, email.Data, errRenew.Error())
|
assert.Contains(t, email.Data, errRenew.Error())
|
||||||
|
|
||||||
_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
|
_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
|
||||||
|
@ -7208,7 +7210,7 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
// ignored no more certificate rules
|
// ignored no more certificate rules
|
||||||
common.HandleCertificateEvent(common.EventParams{
|
common.HandleCertificateEvent(common.EventParams{
|
||||||
Name: "example.com",
|
Name: "example.com",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
Event: renewalEvent,
|
Event: renewalEvent,
|
||||||
})
|
})
|
||||||
|
|
|
@ -408,7 +408,7 @@ func (t *oidcToken) getUser(r *http.Request) error {
|
||||||
Name: t.Username,
|
Name: t.Username,
|
||||||
IP: ipAddr,
|
IP: ipAddr,
|
||||||
Protocol: common.ProtocolOIDC,
|
Protocol: common.ProtocolOIDC,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
}
|
}
|
||||||
if t.isAdmin() {
|
if t.isAdmin() {
|
||||||
|
|
|
@ -1057,6 +1057,7 @@
|
||||||
"ip": "Client IP address",
|
"ip": "Client IP address",
|
||||||
"role": "User or admin role",
|
"role": "User or admin role",
|
||||||
"timestamp": "Event timestamp as nanoseconds since epoch",
|
"timestamp": "Event timestamp as nanoseconds since epoch",
|
||||||
|
"datetime": "Event timestamp formatted as YYYY-MM-DDTHH:MM:SS.ZZZ",
|
||||||
"email": "For filesystem events, this is the email associated with the user performing the action. For the provider events, this is the email associated with the affected user or admin. Blank in all other cases",
|
"email": "For filesystem events, this is the email associated with the user performing the action. For the provider events, this is the email associated with the affected user or admin. Blank in all other cases",
|
||||||
"object_data": "Provider object data serialized as JSON with sensitive fields removed",
|
"object_data": "Provider object data serialized as JSON with sensitive fields removed",
|
||||||
"object_data_string": "Provider object data as JSON escaped string with sensitive fields removed",
|
"object_data_string": "Provider object data as JSON escaped string with sensitive fields removed",
|
||||||
|
|
|
@ -1057,6 +1057,7 @@
|
||||||
"ip": "Indirizzo IP del client",
|
"ip": "Indirizzo IP del client",
|
||||||
"role": "Ruolo dell'utente o dell'amministratore",
|
"role": "Ruolo dell'utente o dell'amministratore",
|
||||||
"timestamp": "Timestamp dell'evento in nanosecondi dall'epoch time",
|
"timestamp": "Timestamp dell'evento in nanosecondi dall'epoch time",
|
||||||
|
"datetime": "Timestamp dell'evento formattato come YYYY-MM-DDTHH:MM:SS.ZZZ",
|
||||||
"email": "Per gli eventi del file system, questa è l'e-mail associata all'utente che esegue l'azione. Per gli eventi del provider, si tratta dell'e-mail associata all'utente o all'amministratore interessato. Vuoto in tutti gli altri casi",
|
"email": "Per gli eventi del file system, questa è l'e-mail associata all'utente che esegue l'azione. Per gli eventi del provider, si tratta dell'e-mail associata all'utente o all'amministratore interessato. Vuoto in tutti gli altri casi",
|
||||||
"object_data": "Dati dell'oggetto provider serializzati come JSON con campi sensibili rimossi",
|
"object_data": "Dati dell'oggetto provider serializzati come JSON con campi sensibili rimossi",
|
||||||
"object_data_string": "Dati dell'oggetto provider serializzati come stringa JSON escaped con campi sensibili rimossi",
|
"object_data_string": "Dati dell'oggetto provider serializzati come stringa JSON escaped con campi sensibili rimossi",
|
||||||
|
|
|
@ -941,6 +941,9 @@ explicit grant from the SFTPGo Team (support@sftpgo.com).
|
||||||
<p>
|
<p>
|
||||||
<span class="shortcut">{{`{{Timestamp}}`}}</span> => <span data-i18n="actions.placeholders_modal.timestamp">Event timestamp as nanoseconds since epoch.</span>
|
<span class="shortcut">{{`{{Timestamp}}`}}</span> => <span data-i18n="actions.placeholders_modal.timestamp">Event timestamp as nanoseconds since epoch.</span>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="shortcut">{{`{{DateTime}}`}}</span> => <span data-i18n="actions.placeholders_modal.datetime">Timestamp formatted as YYYY-MM-DDTHH:MM:SS.ZZZ.</span>
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="shortcut">{{`{{Email}}`}}</span> => <span data-i18n="actions.placeholders_modal.email">For filesystem events, this is the email associated with the user performing the action. For the provider events, this is the email associated with the affected user or admin. Blank in all other cases.</span>
|
<span class="shortcut">{{`{{Email}}`}}</span> => <span data-i18n="actions.placeholders_modal.email">For filesystem events, this is the email associated with the user performing the action. For the provider events, this is the email associated with the affected user or admin. Blank in all other cases.</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
Loading…
Reference in a new issue