eventmanager placeholders: add StatusString and ErrorString
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
37d98ca290
commit
56bf51277c
9 changed files with 285 additions and 150 deletions
|
@ -23,6 +23,8 @@ The following placeholders are supported:
|
||||||
- `{{Name}}`. Username, folder name or admin username for provider actions.
|
- `{{Name}}`. Username, folder name or admin username for provider actions.
|
||||||
- `{{Event}}`. Event name, for example `upload`, `download` for filesystem events or `add`, `update` for provider events.
|
- `{{Event}}`. Event name, for example `upload`, `download` for filesystem events or `add`, `update` for provider events.
|
||||||
- `{{Status}}`. Status for `upload`, `download` and `ssh_cmd` events. 1 means no error, 2 means a generic error occurred, 3 means quota exceeded error.
|
- `{{Status}}`. Status for `upload`, `download` and `ssh_cmd` events. 1 means no error, 2 means a generic error occurred, 3 means quota exceeded error.
|
||||||
|
- `{{StatusString}}`. Status as string. Possible values "OK", "KO".
|
||||||
|
- `{{ErrorString}}`. Error details. Replaced with an empty string if no errors occur.
|
||||||
- `{{VirtualPath}}`. Path seen by SFTPGo users, for example `/adir/afile.txt`.
|
- `{{VirtualPath}}`. Path seen by SFTPGo users, for example `/adir/afile.txt`.
|
||||||
- `{{FsPath}}`. Full filesystem path, for example `/user/homedir/adir/afile.txt` or `C:/data/user/homedir/adir/afile.txt` on Windows.
|
- `{{FsPath}}`. Full filesystem path, for example `/user/homedir/adir/afile.txt` or `C:/data/user/homedir/adir/afile.txt` on Windows.
|
||||||
- `{{ObjectName}}`. File/directory name, for example `afile.txt` or provider object name.
|
- `{{ObjectName}}`. File/directory name, for example `afile.txt` or provider object name.
|
||||||
|
@ -51,7 +53,7 @@ Actions such as user quota reset, transfer quota reset, data retention check, fo
|
||||||
Actions are executed in a sequential order except for sync actions that are executed before the others. For each action associated to a rule you can define the following settings:
|
Actions are executed in a sequential order except for sync actions that are executed before the others. For each action associated to a rule you can define the following settings:
|
||||||
|
|
||||||
- `Stop on failure`, the next action will not be executed if the current one fails.
|
- `Stop on failure`, the next action will not be executed if the current one fails.
|
||||||
- `Failure action`, this action will be executed only if at least another one fails.
|
- `Failure action`, this action will be executed only if at least another one fails. :warning: Please note that a failure action isn't executed if the event fails, for example if a download fails the main action is executed. The failure action is executed only if one of the non-failure actions associated to a rule fails.
|
||||||
- `Execute sync`, for upload events, you can execute the action synchronously. Executing an action synchronously means that SFTPGo will not return a result code to the client (which is waiting for it) until your action have completed its execution. If your acion takes a long time to complete this could cause a timeout on the client side, which wouldn't receive the server response in a timely manner and eventually drop the connection.
|
- `Execute sync`, for upload events, you can execute the action synchronously. Executing an action synchronously means that SFTPGo will not return a result code to the client (which is waiting for it) until your action have completed its execution. If your acion takes a long time to complete this could cause a timeout on the client side, which wouldn't receive the server response in a timely manner and eventually drop the connection.
|
||||||
|
|
||||||
If you are running multiple SFTPGo instances connected to the same data provider, you can choose whether to allow simultaneous execution for scheduled actions.
|
If you are running multiple SFTPGo instances connected to the same data provider, you can choose whether to allow simultaneous execution for scheduled actions.
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -50,7 +50,7 @@ require (
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5
|
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5
|
||||||
github.com/rs/xid v1.4.0
|
github.com/rs/xid v1.4.0
|
||||||
github.com/rs/zerolog v1.27.0
|
github.com/rs/zerolog v1.28.0
|
||||||
github.com/sftpgo/sdk v0.1.2-0.20220828084006-f9e2fffac657
|
github.com/sftpgo/sdk v0.1.2-0.20220828084006-f9e2fffac657
|
||||||
github.com/shirou/gopsutil/v3 v3.22.7
|
github.com/shirou/gopsutil/v3 v3.22.7
|
||||||
github.com/spf13/afero v1.9.2
|
github.com/spf13/afero v1.9.2
|
||||||
|
@ -155,7 +155,7 @@ require (
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
golang.org/x/tools v0.1.12 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
|
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc // indirect
|
google.golang.org/genproto v0.0.0-20220829144015-23454907ede3 // indirect
|
||||||
google.golang.org/grpc v1.49.0 // indirect
|
google.golang.org/grpc v1.49.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -701,13 +701,12 @@ github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBO
|
||||||
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5 h1:7PcjxKTsfGXpTMiTNNa1VllbsYSZJN5nhvVEWQMdX8Y=
|
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5 h1:7PcjxKTsfGXpTMiTNNa1VllbsYSZJN5nhvVEWQMdX8Y=
|
||||||
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
github.com/rs/cors v1.8.3-0.20220619195839-da52b0701de5/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
|
||||||
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
|
||||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||||
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
|
||||||
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
|
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
|
@ -1221,8 +1220,8 @@ google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP
|
||||||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||||
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc h1:Nf+EdcTLHR8qDNN/KfkQL0u0ssxt9OhbaWCl5C0ucEI=
|
google.golang.org/genproto v0.0.0-20220829144015-23454907ede3 h1:4wwmycAWg7WUIFWgzxP6Wumy2GBLxmATgkhgpFnJl2U=
|
||||||
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
|
google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
|
|
@ -568,14 +568,14 @@ func (c *Configuration) notifyCertificateRenewal(domain string, err error) {
|
||||||
}
|
}
|
||||||
params := common.EventParams{
|
params := common.EventParams{
|
||||||
Name: domain,
|
Name: domain,
|
||||||
|
Event: "Certificate renewal",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().UnixNano(),
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
params.Status = 2
|
params.Status = 2
|
||||||
params.Event = "Certificate renewal failed"
|
params.AddError(err)
|
||||||
} else {
|
} else {
|
||||||
params.Status = 1
|
params.Status = 1
|
||||||
params.Event = "Successful certificate renewal"
|
|
||||||
}
|
}
|
||||||
common.HandleCertificateEvent(params)
|
common.HandleCertificateEvent(params)
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtua
|
||||||
}
|
}
|
||||||
var errRes error
|
var errRes error
|
||||||
if hasRules {
|
if hasRules {
|
||||||
errRes = eventManager.handleFsEvent(EventParams{
|
params := EventParams{
|
||||||
Name: notification.Username,
|
Name: notification.Username,
|
||||||
Event: notification.Action,
|
Event: notification.Action,
|
||||||
Status: notification.Status,
|
Status: notification.Status,
|
||||||
|
@ -136,7 +136,11 @@ func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtua
|
||||||
IP: notification.IP,
|
IP: notification.IP,
|
||||||
Timestamp: notification.Timestamp,
|
Timestamp: notification.Timestamp,
|
||||||
Object: nil,
|
Object: nil,
|
||||||
})
|
}
|
||||||
|
if err != nil {
|
||||||
|
params.AddError(fmt.Errorf("%q failed: %w", params.Event, err))
|
||||||
|
}
|
||||||
|
errRes = eventManager.handleFsEvent(params)
|
||||||
}
|
}
|
||||||
if hasHook {
|
if hasHook {
|
||||||
if util.Contains(Config.Actions.ExecuteSync, operation) {
|
if util.Contains(Config.Actions.ExecuteSync, operation) {
|
||||||
|
|
|
@ -406,21 +406,50 @@ func (r *eventRulesContainer) handleCertificateEvent(params EventParams) {
|
||||||
|
|
||||||
// EventParams defines the supported event parameters
|
// EventParams defines the supported event parameters
|
||||||
type EventParams struct {
|
type EventParams struct {
|
||||||
Name string
|
Name string
|
||||||
Event string
|
Event string
|
||||||
Status int
|
Status int
|
||||||
VirtualPath string
|
VirtualPath string
|
||||||
FsPath string
|
FsPath string
|
||||||
VirtualTargetPath string
|
VirtualTargetPath string
|
||||||
FsTargetPath string
|
FsTargetPath string
|
||||||
ObjectName string
|
ObjectName string
|
||||||
ObjectType string
|
ObjectType string
|
||||||
FileSize int64
|
FileSize int64
|
||||||
Protocol string
|
Protocol string
|
||||||
IP string
|
IP string
|
||||||
Timestamp int64
|
Timestamp int64
|
||||||
Object plugin.Renderer
|
Object plugin.Renderer
|
||||||
sender string
|
sender string
|
||||||
|
updateStatusFromError bool
|
||||||
|
errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EventParams) getACopy() *EventParams {
|
||||||
|
params := *p
|
||||||
|
params.errors = make([]string, len(p.errors))
|
||||||
|
copy(params.errors, p.errors)
|
||||||
|
return ¶ms
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddError adds a new error to the event params and update the status if needed
|
||||||
|
func (p *EventParams) AddError(err error) {
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.updateStatusFromError && p.Status == 1 {
|
||||||
|
p.Status = 2
|
||||||
|
}
|
||||||
|
p.errors = append(p.errors, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EventParams) getStatusString() string {
|
||||||
|
switch p.Status {
|
||||||
|
case 1:
|
||||||
|
return "OK"
|
||||||
|
default:
|
||||||
|
return "KO"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUsers returns users with group settings not applied
|
// getUsers returns users with group settings not applied
|
||||||
|
@ -469,11 +498,18 @@ func (p *EventParams) getStringReplacements(addObjectData bool) []string {
|
||||||
"{{Protocol}}", p.Protocol,
|
"{{Protocol}}", p.Protocol,
|
||||||
"{{IP}}", p.IP,
|
"{{IP}}", p.IP,
|
||||||
"{{Timestamp}}", fmt.Sprintf("%d", p.Timestamp),
|
"{{Timestamp}}", fmt.Sprintf("%d", p.Timestamp),
|
||||||
|
"{{StatusString}}", p.getStatusString(),
|
||||||
}
|
}
|
||||||
|
if len(p.errors) > 0 {
|
||||||
|
replacements = append(replacements, "{{ErrorString}}", strings.Join(p.errors, ", "))
|
||||||
|
} else {
|
||||||
|
replacements = append(replacements, "{{ErrorString}}", "")
|
||||||
|
}
|
||||||
|
replacements = append(replacements, "{{ObjectData}}", "")
|
||||||
if addObjectData {
|
if addObjectData {
|
||||||
data, err := p.Object.RenderAsJSON(p.Event != operationDelete)
|
data, err := p.Object.RenderAsJSON(p.Event != operationDelete)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
replacements = append(replacements, "{{ObjectData}}", string(data))
|
replacements[len(replacements)-1] = string(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return replacements
|
return replacements
|
||||||
|
@ -516,7 +552,7 @@ func getMailAttachments(user dataprovider.User, attachments []string, replacer *
|
||||||
err = user.CheckFsRoot(connectionID)
|
err = user.CheckFsRoot(connectionID)
|
||||||
defer user.CloseFs() //nolint:errcheck
|
defer user.CloseFs() //nolint:errcheck
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("error getting email attachments, unable to check root fs for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
||||||
totalSize := int64(0)
|
totalSize := int64(0)
|
||||||
|
@ -596,7 +632,7 @@ func getHTTPRuleActionEndpoint(c dataprovider.EventActionHTTPConfig, replacer *s
|
||||||
return c.Endpoint, nil
|
return c.Endpoint, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeHTTPRuleAction(c dataprovider.EventActionHTTPConfig, params EventParams) error {
|
func executeHTTPRuleAction(c dataprovider.EventActionHTTPConfig, params *EventParams) error {
|
||||||
if !c.Password.IsEmpty() {
|
if !c.Password.IsEmpty() {
|
||||||
if err := c.Password.TryDecrypt(); err != nil {
|
if err := c.Password.TryDecrypt(); err != nil {
|
||||||
return fmt.Errorf("unable to decrypt password: %w", err)
|
return fmt.Errorf("unable to decrypt password: %w", err)
|
||||||
|
@ -653,7 +689,7 @@ func executeHTTPRuleAction(c dataprovider.EventActionHTTPConfig, params EventPar
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeCommandRuleAction(c dataprovider.EventActionCommandConfig, params EventParams) error {
|
func executeCommandRuleAction(c dataprovider.EventActionCommandConfig, params *EventParams) error {
|
||||||
envVars := make([]string, 0, len(c.EnvVars))
|
envVars := make([]string, 0, len(c.EnvVars))
|
||||||
addObjectData := false
|
addObjectData := false
|
||||||
if params.Object != nil {
|
if params.Object != nil {
|
||||||
|
@ -686,7 +722,7 @@ func executeCommandRuleAction(c dataprovider.EventActionCommandConfig, params Ev
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeEmailRuleAction(c dataprovider.EventActionEmailConfig, params EventParams) error {
|
func executeEmailRuleAction(c dataprovider.EventActionEmailConfig, params *EventParams) error {
|
||||||
addObjectData := false
|
addObjectData := false
|
||||||
if params.Object != nil {
|
if params.Object != nil {
|
||||||
if strings.Contains(c.Body, "{{ObjectData}}") {
|
if strings.Contains(c.Body, "{{ObjectData}}") {
|
||||||
|
@ -748,7 +784,7 @@ func executeDeleteFsActionForUser(deletes []string, replacer *strings.Replacer,
|
||||||
err = user.CheckFsRoot(connectionID)
|
err = user.CheckFsRoot(connectionID)
|
||||||
defer user.CloseFs() //nolint:errcheck
|
defer user.CloseFs() //nolint:errcheck
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("delete error, unable to check root fs for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
||||||
for _, item := range deletes {
|
for _, item := range deletes {
|
||||||
|
@ -775,7 +811,7 @@ func executeDeleteFsActionForUser(deletes []string, replacer *strings.Replacer,
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeDeleteFsRuleAction(deletes []string, replacer *strings.Replacer,
|
func executeDeleteFsRuleAction(deletes []string, replacer *strings.Replacer,
|
||||||
conditions dataprovider.ConditionOptions, params EventParams,
|
conditions dataprovider.ConditionOptions, params *EventParams,
|
||||||
) error {
|
) error {
|
||||||
users, err := params.getUsers()
|
users, err := params.getUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -792,6 +828,7 @@ func executeDeleteFsRuleAction(deletes []string, replacer *strings.Replacer,
|
||||||
}
|
}
|
||||||
executed++
|
executed++
|
||||||
if err = executeDeleteFsActionForUser(deletes, replacer, user); err != nil {
|
if err = executeDeleteFsActionForUser(deletes, replacer, user); err != nil {
|
||||||
|
params.AddError(err)
|
||||||
failures = append(failures, user.Username)
|
failures = append(failures, user.Username)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -815,7 +852,7 @@ func executeMkDirsFsActionForUser(dirs []string, replacer *strings.Replacer, use
|
||||||
err = user.CheckFsRoot(connectionID)
|
err = user.CheckFsRoot(connectionID)
|
||||||
defer user.CloseFs() //nolint:errcheck
|
defer user.CloseFs() //nolint:errcheck
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("mkdir error, unable to check root fs for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
||||||
for _, item := range dirs {
|
for _, item := range dirs {
|
||||||
|
@ -832,7 +869,7 @@ func executeMkDirsFsActionForUser(dirs []string, replacer *strings.Replacer, use
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeMkdirFsRuleAction(dirs []string, replacer *strings.Replacer,
|
func executeMkdirFsRuleAction(dirs []string, replacer *strings.Replacer,
|
||||||
conditions dataprovider.ConditionOptions, params EventParams,
|
conditions dataprovider.ConditionOptions, params *EventParams,
|
||||||
) error {
|
) error {
|
||||||
users, err := params.getUsers()
|
users, err := params.getUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -874,7 +911,7 @@ func executeRenameFsActionForUser(renames []dataprovider.KeyValue, replacer *str
|
||||||
err = user.CheckFsRoot(connectionID)
|
err = user.CheckFsRoot(connectionID)
|
||||||
defer user.CloseFs() //nolint:errcheck
|
defer user.CloseFs() //nolint:errcheck
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("rename error, unable to check root fs for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
||||||
for _, item := range renames {
|
for _, item := range renames {
|
||||||
|
@ -899,7 +936,7 @@ func executeExistFsActionForUser(exist []string, replacer *strings.Replacer,
|
||||||
err = user.CheckFsRoot(connectionID)
|
err = user.CheckFsRoot(connectionID)
|
||||||
defer user.CloseFs() //nolint:errcheck
|
defer user.CloseFs() //nolint:errcheck
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("existence check error, unable to check root fs for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
conn := NewBaseConnection(connectionID, protocolEventAction, "", "", user)
|
||||||
for _, item := range exist {
|
for _, item := range exist {
|
||||||
|
@ -913,7 +950,7 @@ func executeExistFsActionForUser(exist []string, replacer *strings.Replacer,
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeRenameFsRuleAction(renames []dataprovider.KeyValue, replacer *strings.Replacer,
|
func executeRenameFsRuleAction(renames []dataprovider.KeyValue, replacer *strings.Replacer,
|
||||||
conditions dataprovider.ConditionOptions, params EventParams,
|
conditions dataprovider.ConditionOptions, params *EventParams,
|
||||||
) error {
|
) error {
|
||||||
users, err := params.getUsers()
|
users, err := params.getUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -931,6 +968,7 @@ func executeRenameFsRuleAction(renames []dataprovider.KeyValue, replacer *string
|
||||||
executed++
|
executed++
|
||||||
if err = executeRenameFsActionForUser(renames, replacer, user); err != nil {
|
if err = executeRenameFsActionForUser(renames, replacer, user); err != nil {
|
||||||
failures = append(failures, user.Username)
|
failures = append(failures, user.Username)
|
||||||
|
params.AddError(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -945,7 +983,7 @@ func executeRenameFsRuleAction(renames []dataprovider.KeyValue, replacer *string
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeExistFsRuleAction(exist []string, replacer *strings.Replacer, conditions dataprovider.ConditionOptions,
|
func executeExistFsRuleAction(exist []string, replacer *strings.Replacer, conditions dataprovider.ConditionOptions,
|
||||||
params EventParams,
|
params *EventParams,
|
||||||
) error {
|
) error {
|
||||||
users, err := params.getUsers()
|
users, err := params.getUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -963,6 +1001,7 @@ func executeExistFsRuleAction(exist []string, replacer *strings.Replacer, condit
|
||||||
executed++
|
executed++
|
||||||
if err = executeExistFsActionForUser(exist, replacer, user); err != nil {
|
if err = executeExistFsActionForUser(exist, replacer, user); err != nil {
|
||||||
failures = append(failures, user.Username)
|
failures = append(failures, user.Username)
|
||||||
|
params.AddError(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -977,7 +1016,7 @@ func executeExistFsRuleAction(exist []string, replacer *strings.Replacer, condit
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeFsRuleAction(c dataprovider.EventActionFilesystemConfig, conditions dataprovider.ConditionOptions,
|
func executeFsRuleAction(c dataprovider.EventActionFilesystemConfig, conditions dataprovider.ConditionOptions,
|
||||||
params EventParams,
|
params *EventParams,
|
||||||
) error {
|
) error {
|
||||||
addObjectData := false
|
addObjectData := false
|
||||||
replacements := params.getStringReplacements(addObjectData)
|
replacements := params.getStringReplacements(addObjectData)
|
||||||
|
@ -1003,25 +1042,25 @@ func executeQuotaResetForUser(user dataprovider.User) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !QuotaScans.AddUserQuotaScan(user.Username) {
|
if !QuotaScans.AddUserQuotaScan(user.Username) {
|
||||||
eventManagerLog(logger.LevelError, "another quota scan is already in progress for user %s", user.Username)
|
eventManagerLog(logger.LevelError, "another quota scan is already in progress for user %q", user.Username)
|
||||||
return fmt.Errorf("another quota scan is in progress for user %s", user.Username)
|
return fmt.Errorf("another quota scan is in progress for user %q", user.Username)
|
||||||
}
|
}
|
||||||
defer QuotaScans.RemoveUserQuotaScan(user.Username)
|
defer QuotaScans.RemoveUserQuotaScan(user.Username)
|
||||||
|
|
||||||
numFiles, size, err := user.ScanQuota()
|
numFiles, size, err := user.ScanQuota()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
eventManagerLog(logger.LevelError, "error scanning quota for user %s: %v", user.Username, err)
|
eventManagerLog(logger.LevelError, "error scanning quota for user %q: %v", user.Username, err)
|
||||||
return err
|
return fmt.Errorf("error scanning quota for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
err = dataprovider.UpdateUserQuota(&user, numFiles, size, true)
|
err = dataprovider.UpdateUserQuota(&user, numFiles, size, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
eventManagerLog(logger.LevelError, "error updating quota for user %s: %v", user.Username, err)
|
eventManagerLog(logger.LevelError, "error updating quota for user %q: %v", user.Username, err)
|
||||||
return err
|
return fmt.Errorf("error updating quota for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeUsersQuotaResetRuleAction(conditions dataprovider.ConditionOptions, params EventParams) error {
|
func executeUsersQuotaResetRuleAction(conditions dataprovider.ConditionOptions, params *EventParams) error {
|
||||||
users, err := params.getUsers()
|
users, err := params.getUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get users: %w", err)
|
return fmt.Errorf("unable to get users: %w", err)
|
||||||
|
@ -1031,12 +1070,13 @@ func executeUsersQuotaResetRuleAction(conditions dataprovider.ConditionOptions,
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
// if sender is set, the conditions have already been evaluated
|
// if sender is set, the conditions have already been evaluated
|
||||||
if params.sender == "" && !checkEventConditionPatterns(user.Username, conditions.Names) {
|
if params.sender == "" && !checkEventConditionPatterns(user.Username, conditions.Names) {
|
||||||
eventManagerLog(logger.LevelDebug, "skipping scheduled quota reset for user %s, name conditions don't match",
|
eventManagerLog(logger.LevelDebug, "skipping quota reset for user %q, name conditions don't match",
|
||||||
user.Username)
|
user.Username)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
executed++
|
executed++
|
||||||
if err = executeQuotaResetForUser(user); err != nil {
|
if err = executeQuotaResetForUser(user); err != nil {
|
||||||
|
params.AddError(err)
|
||||||
failedResets = append(failedResets, user.Username)
|
failedResets = append(failedResets, user.Username)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1051,7 +1091,7 @@ func executeUsersQuotaResetRuleAction(conditions dataprovider.ConditionOptions,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeFoldersQuotaResetRuleAction(conditions dataprovider.ConditionOptions, params EventParams) error {
|
func executeFoldersQuotaResetRuleAction(conditions dataprovider.ConditionOptions, params *EventParams) error {
|
||||||
folders, err := params.getFolders()
|
folders, err := params.getFolders()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get folders: %w", err)
|
return fmt.Errorf("unable to get folders: %w", err)
|
||||||
|
@ -1066,7 +1106,8 @@ func executeFoldersQuotaResetRuleAction(conditions dataprovider.ConditionOptions
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !QuotaScans.AddVFolderQuotaScan(folder.Name) {
|
if !QuotaScans.AddVFolderQuotaScan(folder.Name) {
|
||||||
eventManagerLog(logger.LevelError, "another quota scan is already in progress for folder %s", folder.Name)
|
eventManagerLog(logger.LevelError, "another quota scan is already in progress for folder %q", folder.Name)
|
||||||
|
params.AddError(fmt.Errorf("another quota scan is already in progress for folder %q", folder.Name))
|
||||||
failedResets = append(failedResets, folder.Name)
|
failedResets = append(failedResets, folder.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1078,13 +1119,15 @@ func executeFoldersQuotaResetRuleAction(conditions dataprovider.ConditionOptions
|
||||||
numFiles, size, err := f.ScanQuota()
|
numFiles, size, err := f.ScanQuota()
|
||||||
QuotaScans.RemoveVFolderQuotaScan(folder.Name)
|
QuotaScans.RemoveVFolderQuotaScan(folder.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
eventManagerLog(logger.LevelError, "error scanning quota for folder %s: %v", folder.Name, err)
|
eventManagerLog(logger.LevelError, "error scanning quota for folder %q: %v", folder.Name, err)
|
||||||
|
params.AddError(fmt.Errorf("error scanning quota for folder %q: %w", folder.Name, err))
|
||||||
failedResets = append(failedResets, folder.Name)
|
failedResets = append(failedResets, folder.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err = dataprovider.UpdateVirtualFolderQuota(&folder, numFiles, size, true)
|
err = dataprovider.UpdateVirtualFolderQuota(&folder, numFiles, size, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
eventManagerLog(logger.LevelError, "error updating quota for folder %s: %v", folder.Name, err)
|
eventManagerLog(logger.LevelError, "error updating quota for folder %q: %v", folder.Name, err)
|
||||||
|
params.AddError(fmt.Errorf("error updating quota for folder %q: %w", folder.Name, err))
|
||||||
failedResets = append(failedResets, folder.Name)
|
failedResets = append(failedResets, folder.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1098,7 +1141,7 @@ func executeFoldersQuotaResetRuleAction(conditions dataprovider.ConditionOptions
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeTransferQuotaResetRuleAction(conditions dataprovider.ConditionOptions, params EventParams) error {
|
func executeTransferQuotaResetRuleAction(conditions dataprovider.ConditionOptions, params *EventParams) error {
|
||||||
users, err := params.getUsers()
|
users, err := params.getUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get users: %w", err)
|
return fmt.Errorf("unable to get users: %w", err)
|
||||||
|
@ -1115,7 +1158,8 @@ func executeTransferQuotaResetRuleAction(conditions dataprovider.ConditionOption
|
||||||
executed++
|
executed++
|
||||||
err = dataprovider.UpdateUserTransferQuota(&user, 0, 0, true)
|
err = dataprovider.UpdateUserTransferQuota(&user, 0, 0, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
eventManagerLog(logger.LevelError, "error updating transfer quota for user %s: %v", user.Username, err)
|
eventManagerLog(logger.LevelError, "error updating transfer quota for user %q: %v", user.Username, err)
|
||||||
|
params.AddError(fmt.Errorf("error updating transfer quota for user %q: %w", user.Username, err))
|
||||||
failedResets = append(failedResets, user.Username)
|
failedResets = append(failedResets, user.Username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1140,18 +1184,18 @@ func executeDataRetentionCheckForUser(user dataprovider.User, folders []dataprov
|
||||||
}
|
}
|
||||||
c := RetentionChecks.Add(check, &user)
|
c := RetentionChecks.Add(check, &user)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
eventManagerLog(logger.LevelError, "another retention check is already in progress for user %s", user.Username)
|
eventManagerLog(logger.LevelError, "another retention check is already in progress for user %q", user.Username)
|
||||||
return fmt.Errorf("another retention check is in progress for user %s", user.Username)
|
return fmt.Errorf("another retention check is in progress for user %q", user.Username)
|
||||||
}
|
}
|
||||||
if err := c.Start(); err != nil {
|
if err := c.Start(); err != nil {
|
||||||
eventManagerLog(logger.LevelError, "error checking retention for user %s: %v", user.Username, err)
|
eventManagerLog(logger.LevelError, "error checking retention for user %q: %v", user.Username, err)
|
||||||
return err
|
return fmt.Errorf("error checking retention for user %q: %w", user.Username, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeDataRetentionCheckRuleAction(config dataprovider.EventActionDataRetentionConfig,
|
func executeDataRetentionCheckRuleAction(config dataprovider.EventActionDataRetentionConfig,
|
||||||
conditions dataprovider.ConditionOptions, params EventParams,
|
conditions dataprovider.ConditionOptions, params *EventParams,
|
||||||
) error {
|
) error {
|
||||||
users, err := params.getUsers()
|
users, err := params.getUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1169,6 +1213,7 @@ func executeDataRetentionCheckRuleAction(config dataprovider.EventActionDataRete
|
||||||
executed++
|
executed++
|
||||||
if err = executeDataRetentionCheckForUser(user, config.Folders); err != nil {
|
if err = executeDataRetentionCheckForUser(user, config.Folders); err != nil {
|
||||||
failedChecks = append(failedChecks, user.Username)
|
failedChecks = append(failedChecks, user.Username)
|
||||||
|
params.AddError(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1182,29 +1227,37 @@ func executeDataRetentionCheckRuleAction(config dataprovider.EventActionDataRete
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeRuleAction(action dataprovider.BaseEventAction, params EventParams, conditions dataprovider.ConditionOptions) error {
|
func executeRuleAction(action dataprovider.BaseEventAction, params *EventParams, conditions dataprovider.ConditionOptions) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
switch action.Type {
|
switch action.Type {
|
||||||
case dataprovider.ActionTypeHTTP:
|
case dataprovider.ActionTypeHTTP:
|
||||||
return executeHTTPRuleAction(action.Options.HTTPConfig, params)
|
err = executeHTTPRuleAction(action.Options.HTTPConfig, params)
|
||||||
case dataprovider.ActionTypeCommand:
|
case dataprovider.ActionTypeCommand:
|
||||||
return executeCommandRuleAction(action.Options.CmdConfig, params)
|
err = executeCommandRuleAction(action.Options.CmdConfig, params)
|
||||||
case dataprovider.ActionTypeEmail:
|
case dataprovider.ActionTypeEmail:
|
||||||
return executeEmailRuleAction(action.Options.EmailConfig, params)
|
err = executeEmailRuleAction(action.Options.EmailConfig, params)
|
||||||
case dataprovider.ActionTypeBackup:
|
case dataprovider.ActionTypeBackup:
|
||||||
return dataprovider.ExecuteBackup()
|
err = dataprovider.ExecuteBackup()
|
||||||
case dataprovider.ActionTypeUserQuotaReset:
|
case dataprovider.ActionTypeUserQuotaReset:
|
||||||
return executeUsersQuotaResetRuleAction(conditions, params)
|
err = executeUsersQuotaResetRuleAction(conditions, params)
|
||||||
case dataprovider.ActionTypeFolderQuotaReset:
|
case dataprovider.ActionTypeFolderQuotaReset:
|
||||||
return executeFoldersQuotaResetRuleAction(conditions, params)
|
err = executeFoldersQuotaResetRuleAction(conditions, params)
|
||||||
case dataprovider.ActionTypeTransferQuotaReset:
|
case dataprovider.ActionTypeTransferQuotaReset:
|
||||||
return executeTransferQuotaResetRuleAction(conditions, params)
|
err = executeTransferQuotaResetRuleAction(conditions, params)
|
||||||
case dataprovider.ActionTypeDataRetentionCheck:
|
case dataprovider.ActionTypeDataRetentionCheck:
|
||||||
return executeDataRetentionCheckRuleAction(action.Options.RetentionConfig, conditions, params)
|
err = executeDataRetentionCheckRuleAction(action.Options.RetentionConfig, conditions, params)
|
||||||
case dataprovider.ActionTypeFilesystem:
|
case dataprovider.ActionTypeFilesystem:
|
||||||
return executeFsRuleAction(action.Options.FsConfig, conditions, params)
|
err = executeFsRuleAction(action.Options.FsConfig, conditions, params)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported action type: %d", action.Type)
|
err = fmt.Errorf("unsupported action type: %d", action.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("action %q failed: %w", action.Name, err)
|
||||||
|
}
|
||||||
|
params.AddError(err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeSyncRulesActions(rules []dataprovider.EventRule, params EventParams) error {
|
func executeSyncRulesActions(rules []dataprovider.EventRule, params EventParams) error {
|
||||||
|
@ -1212,10 +1265,11 @@ func executeSyncRulesActions(rules []dataprovider.EventRule, params EventParams)
|
||||||
|
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
var failedActions []string
|
var failedActions []string
|
||||||
|
paramsCopy := params.getACopy()
|
||||||
for _, action := range rule.Actions {
|
for _, action := range rule.Actions {
|
||||||
if !action.Options.IsFailureAction && action.Options.ExecuteSync {
|
if !action.Options.IsFailureAction && action.Options.ExecuteSync {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
if err := executeRuleAction(action.BaseEventAction, params, rule.Conditions.Options); err != nil {
|
if err := executeRuleAction(action.BaseEventAction, paramsCopy, rule.Conditions.Options); err != nil {
|
||||||
eventManagerLog(logger.LevelError, "unable to execute sync action %q for rule %q, elapsed %s, err: %v",
|
eventManagerLog(logger.LevelError, "unable to execute sync action %q for rule %q, elapsed %s, err: %v",
|
||||||
action.Name, rule.Name, time.Since(startTime), err)
|
action.Name, rule.Name, time.Since(startTime), err)
|
||||||
failedActions = append(failedActions, action.Name)
|
failedActions = append(failedActions, action.Name)
|
||||||
|
@ -1231,7 +1285,7 @@ func executeSyncRulesActions(rules []dataprovider.EventRule, params EventParams)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// execute async actions if any, including failure actions
|
// execute async actions if any, including failure actions
|
||||||
go executeRuleAsyncActions(rule, params, failedActions)
|
go executeRuleAsyncActions(rule, paramsCopy, failedActions)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errRes
|
return errRes
|
||||||
|
@ -1242,11 +1296,11 @@ func executeAsyncRulesActions(rules []dataprovider.EventRule, params EventParams
|
||||||
defer eventManager.removeAsyncTask()
|
defer eventManager.removeAsyncTask()
|
||||||
|
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
executeRuleAsyncActions(rule, params, nil)
|
executeRuleAsyncActions(rule, params.getACopy(), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeRuleAsyncActions(rule dataprovider.EventRule, params EventParams, failedActions []string) {
|
func executeRuleAsyncActions(rule dataprovider.EventRule, params *EventParams, failedActions []string) {
|
||||||
for _, action := range rule.Actions {
|
for _, action := range rule.Actions {
|
||||||
if !action.Options.IsFailureAction && !action.Options.ExecuteSync {
|
if !action.Options.IsFailureAction && !action.Options.ExecuteSync {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
@ -1361,9 +1415,9 @@ func (j *eventCronJob) Run() {
|
||||||
}
|
}
|
||||||
}(task.Name)
|
}(task.Name)
|
||||||
|
|
||||||
executeAsyncRulesActions([]dataprovider.EventRule{rule}, EventParams{})
|
executeAsyncRulesActions([]dataprovider.EventRule{rule}, EventParams{Status: 1, updateStatusFromError: true})
|
||||||
} else {
|
} else {
|
||||||
executeAsyncRulesActions([]dataprovider.EventRule{rule}, EventParams{})
|
executeAsyncRulesActions([]dataprovider.EventRule{rule}, EventParams{Status: 1, updateStatusFromError: true})
|
||||||
}
|
}
|
||||||
eventManagerLog(logger.LevelDebug, "execution for scheduled rule %q finished", j.ruleName)
|
eventManagerLog(logger.LevelDebug, "execution for scheduled rule %q finished", j.ruleName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,19 +270,19 @@ func TestEventManagerErrors(t *testing.T) {
|
||||||
_, err = params.getFolders()
|
_, err = params.getFolders()
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
err = executeUsersQuotaResetRuleAction(dataprovider.ConditionOptions{}, EventParams{})
|
err = executeUsersQuotaResetRuleAction(dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
err = executeFoldersQuotaResetRuleAction(dataprovider.ConditionOptions{}, EventParams{})
|
err = executeFoldersQuotaResetRuleAction(dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
err = executeTransferQuotaResetRuleAction(dataprovider.ConditionOptions{}, EventParams{})
|
err = executeTransferQuotaResetRuleAction(dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
err = executeDeleteFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, EventParams{})
|
err = executeDeleteFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
err = executeMkdirFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, EventParams{})
|
err = executeMkdirFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
err = executeRenameFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, EventParams{})
|
err = executeRenameFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
err = executeExistFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, EventParams{})
|
err = executeExistFsRuleAction(nil, nil, dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
groupName := "agroup"
|
groupName := "agroup"
|
||||||
|
@ -362,7 +362,7 @@ func TestEventManagerErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = executeRuleAction(dataRetentionAction, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(dataRetentionAction, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "username1",
|
Pattern: "username1",
|
||||||
|
@ -421,10 +421,10 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
Name: actionName,
|
Name: actionName,
|
||||||
Type: dataprovider.ActionTypeBackup,
|
Type: dataprovider.ActionTypeBackup,
|
||||||
}
|
}
|
||||||
err := executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{})
|
err := executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
action.Type = -1
|
action.Type = -1
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{})
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
action = dataprovider.BaseEventAction{
|
action = dataprovider.BaseEventAction{
|
||||||
|
@ -454,12 +454,12 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
action.Options.SetEmptySecretsIfNil()
|
action.Options.SetEmptySecretsIfNil()
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{})
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{})
|
||||||
if assert.Error(t, err) {
|
if assert.Error(t, err) {
|
||||||
assert.Contains(t, err.Error(), "invalid endpoint")
|
assert.Contains(t, err.Error(), "invalid endpoint")
|
||||||
}
|
}
|
||||||
action.Options.HTTPConfig.Endpoint = fmt.Sprintf("http://%v", httpAddr)
|
action.Options.HTTPConfig.Endpoint = fmt.Sprintf("http://%v", httpAddr)
|
||||||
params := EventParams{
|
params := &EventParams{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
Object: &dataprovider.User{
|
Object: &dataprovider.User{
|
||||||
BaseUser: sdk.BaseUser{
|
BaseUser: sdk.BaseUser{
|
||||||
|
@ -472,7 +472,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
action.Options.HTTPConfig.Endpoint = fmt.Sprintf("http://%v/404", httpAddr)
|
action.Options.HTTPConfig.Endpoint = fmt.Sprintf("http://%v/404", httpAddr)
|
||||||
err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
|
err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
|
||||||
if assert.Error(t, err) {
|
if assert.Error(t, err) {
|
||||||
assert.Equal(t, err.Error(), "unexpected status code: 404")
|
assert.Contains(t, err.Error(), "unexpected status code: 404")
|
||||||
}
|
}
|
||||||
action.Options.HTTPConfig.Endpoint = "http://invalid:1234"
|
action.Options.HTTPConfig.Endpoint = "http://invalid:1234"
|
||||||
err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
|
err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
|
||||||
|
@ -517,7 +517,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
action = dataprovider.BaseEventAction{
|
action = dataprovider.BaseEventAction{
|
||||||
Type: dataprovider.ActionTypeUserQuotaReset,
|
Type: dataprovider.ActionTypeUserQuotaReset,
|
||||||
}
|
}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -530,7 +530,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = os.WriteFile(filepath.Join(user1.GetHomeDir(), "file.txt"), []byte("user"), 0666)
|
err = os.WriteFile(filepath.Join(user1.GetHomeDir(), "file.txt"), []byte("user"), 0666)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -544,7 +544,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.Equal(t, int64(4), userGet.UsedQuotaSize)
|
assert.Equal(t, int64(4), userGet.UsedQuotaSize)
|
||||||
// simulate another quota scan in progress
|
// simulate another quota scan in progress
|
||||||
assert.True(t, QuotaScans.AddUserQuotaScan(username1))
|
assert.True(t, QuotaScans.AddUserQuotaScan(username1))
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -554,7 +554,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, QuotaScans.RemoveUserQuotaScan(username1))
|
assert.True(t, QuotaScans.RemoveUserQuotaScan(username1))
|
||||||
// non matching pattern
|
// non matching pattern
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "don't match",
|
Pattern: "don't match",
|
||||||
|
@ -578,7 +578,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = executeRuleAction(dataRetentionAction, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(dataRetentionAction, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -622,7 +622,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
err = os.Chtimes(file4, timeBeforeRetention, timeBeforeRetention)
|
err = os.Chtimes(file4, timeBeforeRetention, timeBeforeRetention)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = executeRuleAction(dataRetentionAction, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(dataRetentionAction, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -637,7 +637,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
// simulate another check in progress
|
// simulate another check in progress
|
||||||
c := RetentionChecks.Add(RetentionCheck{}, &user1)
|
c := RetentionChecks.Add(RetentionCheck{}, &user1)
|
||||||
assert.NotNil(t, c)
|
assert.NotNil(t, c)
|
||||||
err = executeRuleAction(dataRetentionAction, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(dataRetentionAction, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -647,7 +647,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
RetentionChecks.remove(user1.Username)
|
RetentionChecks.remove(user1.Username)
|
||||||
|
|
||||||
err = executeRuleAction(dataRetentionAction, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(dataRetentionAction, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "no match",
|
Pattern: "no match",
|
||||||
|
@ -667,7 +667,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "no match",
|
Pattern: "no match",
|
||||||
|
@ -677,7 +677,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
if assert.Error(t, err) {
|
if assert.Error(t, err) {
|
||||||
assert.Contains(t, err.Error(), "no existence check executed")
|
assert.Contains(t, err.Error(), "no existence check executed")
|
||||||
}
|
}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -686,7 +686,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
action.Options.FsConfig.Exist = []string{"/file1.txt", path.Join("/", retentionDir, "file2.txt")}
|
action.Options.FsConfig.Exist = []string{"/file1.txt", path.Join("/", retentionDir, "file2.txt")}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -702,7 +702,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
action.Type = dataprovider.ActionTypeTransferQuotaReset
|
action.Type = dataprovider.ActionTypeTransferQuotaReset
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username1,
|
Pattern: username1,
|
||||||
|
@ -715,7 +715,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.Equal(t, int64(0), userGet.UsedDownloadDataTransfer)
|
assert.Equal(t, int64(0), userGet.UsedDownloadDataTransfer)
|
||||||
assert.Equal(t, int64(0), userGet.UsedUploadDataTransfer)
|
assert.Equal(t, int64(0), userGet.UsedUploadDataTransfer)
|
||||||
|
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "no match",
|
Pattern: "no match",
|
||||||
|
@ -737,7 +737,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "no match",
|
Pattern: "no match",
|
||||||
|
@ -753,7 +753,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
Deletes: []string{"/dir1"},
|
Deletes: []string{"/dir1"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "no match",
|
Pattern: "no match",
|
||||||
|
@ -769,7 +769,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
Deletes: []string{"/dir1"},
|
Deletes: []string{"/dir1"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "no match",
|
Pattern: "no match",
|
||||||
|
@ -802,7 +802,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
action = dataprovider.BaseEventAction{
|
action = dataprovider.BaseEventAction{
|
||||||
Type: dataprovider.ActionTypeFolderQuotaReset,
|
Type: dataprovider.ActionTypeFolderQuotaReset,
|
||||||
}
|
}
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: foldername1,
|
Pattern: foldername1,
|
||||||
|
@ -814,7 +814,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = os.WriteFile(filepath.Join(folder1.MappedPath, "file.txt"), []byte("folder"), 0666)
|
err = os.WriteFile(filepath.Join(folder1.MappedPath, "file.txt"), []byte("folder"), 0666)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: foldername1,
|
Pattern: foldername1,
|
||||||
|
@ -828,7 +828,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.Equal(t, int64(6), folderGet.UsedQuotaSize)
|
assert.Equal(t, int64(6), folderGet.UsedQuotaSize)
|
||||||
// simulate another quota scan in progress
|
// simulate another quota scan in progress
|
||||||
assert.True(t, QuotaScans.AddVFolderQuotaScan(foldername1))
|
assert.True(t, QuotaScans.AddVFolderQuotaScan(foldername1))
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: foldername1,
|
Pattern: foldername1,
|
||||||
|
@ -838,7 +838,7 @@ func TestEventRuleActions(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, QuotaScans.RemoveVFolderQuotaScan(foldername1))
|
assert.True(t, QuotaScans.RemoveVFolderQuotaScan(foldername1))
|
||||||
|
|
||||||
err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
|
err = executeRuleAction(action, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: "no folder match",
|
Pattern: "no folder match",
|
||||||
|
@ -920,7 +920,7 @@ func TestGetFileContent(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilesystemActionErrors(t *testing.T) {
|
func TestFilesystemActionErrors(t *testing.T) {
|
||||||
err := executeFsRuleAction(dataprovider.EventActionFilesystemConfig{}, dataprovider.ConditionOptions{}, EventParams{})
|
err := executeFsRuleAction(dataprovider.EventActionFilesystemConfig{}, dataprovider.ConditionOptions{}, &EventParams{})
|
||||||
if assert.Error(t, err) {
|
if assert.Error(t, err) {
|
||||||
assert.Contains(t, err.Error(), "unsupported filesystem action")
|
assert.Contains(t, err.Error(), "unsupported filesystem action")
|
||||||
}
|
}
|
||||||
|
@ -950,7 +950,7 @@ func TestFilesystemActionErrors(t *testing.T) {
|
||||||
Subject: "subject",
|
Subject: "subject",
|
||||||
Body: "body",
|
Body: "body",
|
||||||
Attachments: []string{"/file.txt"},
|
Attachments: []string{"/file.txt"},
|
||||||
}, EventParams{
|
}, &EventParams{
|
||||||
sender: username,
|
sender: username,
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -973,7 +973,7 @@ func TestFilesystemActionErrors(t *testing.T) {
|
||||||
Subject: "subject",
|
Subject: "subject",
|
||||||
Body: "body",
|
Body: "body",
|
||||||
Attachments: []string{"/file1.txt"},
|
Attachments: []string{"/file1.txt"},
|
||||||
}, EventParams{
|
}, &EventParams{
|
||||||
sender: username,
|
sender: username,
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -1008,7 +1008,7 @@ func TestFilesystemActionErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, EventParams{}, dataprovider.ConditionOptions{
|
}, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username,
|
Pattern: username,
|
||||||
|
@ -1045,7 +1045,7 @@ func TestFilesystemActionErrors(t *testing.T) {
|
||||||
Deletes: []string{"/adir/sub/f.dat"},
|
Deletes: []string{"/adir/sub/f.dat"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, EventParams{}, dataprovider.ConditionOptions{
|
}, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username,
|
Pattern: username,
|
||||||
|
@ -1071,7 +1071,7 @@ func TestFilesystemActionErrors(t *testing.T) {
|
||||||
MkDirs: []string{"/adir/sub/sub1"},
|
MkDirs: []string{"/adir/sub/sub1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, EventParams{}, dataprovider.ConditionOptions{
|
}, &EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username,
|
Pattern: username,
|
||||||
|
@ -1119,7 +1119,7 @@ func TestQuotaActionsWithQuotaTrackDisabled(t *testing.T) {
|
||||||
err = os.MkdirAll(user.GetHomeDir(), os.ModePerm)
|
err = os.MkdirAll(user.GetHomeDir(), os.ModePerm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeUserQuotaReset},
|
err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeUserQuotaReset},
|
||||||
EventParams{}, dataprovider.ConditionOptions{
|
&EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username,
|
Pattern: username,
|
||||||
|
@ -1129,7 +1129,7 @@ func TestQuotaActionsWithQuotaTrackDisabled(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeTransferQuotaReset},
|
err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeTransferQuotaReset},
|
||||||
EventParams{}, dataprovider.ConditionOptions{
|
&EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: username,
|
Pattern: username,
|
||||||
|
@ -1154,7 +1154,7 @@ func TestQuotaActionsWithQuotaTrackDisabled(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeFolderQuotaReset},
|
err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeFolderQuotaReset},
|
||||||
EventParams{}, dataprovider.ConditionOptions{
|
&EventParams{}, dataprovider.ConditionOptions{
|
||||||
Names: []dataprovider.ConditionPattern{
|
Names: []dataprovider.ConditionPattern{
|
||||||
{
|
{
|
||||||
Pattern: foldername,
|
Pattern: foldername,
|
||||||
|
@ -1242,3 +1242,37 @@ func TestScheduledActions(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
stopEventScheduler()
|
stopEventScheduler()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEventParamsCopy(t *testing.T) {
|
||||||
|
params := EventParams{
|
||||||
|
Name: "name",
|
||||||
|
Event: "event",
|
||||||
|
Status: 1,
|
||||||
|
errors: []string{"error1"},
|
||||||
|
}
|
||||||
|
paramsCopy := params.getACopy()
|
||||||
|
assert.Equal(t, params, *paramsCopy)
|
||||||
|
params.Name = "name mod"
|
||||||
|
paramsCopy.Event = "event mod"
|
||||||
|
paramsCopy.Status = 2
|
||||||
|
params.errors = append(params.errors, "error2")
|
||||||
|
paramsCopy.errors = append(paramsCopy.errors, "error3")
|
||||||
|
assert.Equal(t, []string{"error1", "error3"}, paramsCopy.errors)
|
||||||
|
assert.Equal(t, []string{"error1", "error2"}, params.errors)
|
||||||
|
assert.Equal(t, "name mod", params.Name)
|
||||||
|
assert.Equal(t, "name", paramsCopy.Name)
|
||||||
|
assert.Equal(t, "event", params.Event)
|
||||||
|
assert.Equal(t, "event mod", paramsCopy.Event)
|
||||||
|
assert.Equal(t, 1, params.Status)
|
||||||
|
assert.Equal(t, 2, paramsCopy.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEventParamsStatusFromError(t *testing.T) {
|
||||||
|
params := EventParams{Status: 1}
|
||||||
|
params.AddError(os.ErrNotExist)
|
||||||
|
assert.Equal(t, 1, params.Status)
|
||||||
|
|
||||||
|
params = EventParams{Status: 1, updateStatusFromError: true}
|
||||||
|
params.AddError(os.ErrNotExist)
|
||||||
|
assert.Equal(t, 2, params.Status)
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
@ -3064,8 +3065,8 @@ func TestEventRule(t *testing.T) {
|
||||||
Options: dataprovider.BaseEventActionOptions{
|
Options: dataprovider.BaseEventActionOptions{
|
||||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||||
Recipients: []string{"test1@example.com", "test2@example.com"},
|
Recipients: []string{"test1@example.com", "test2@example.com"},
|
||||||
Subject: `New "{{Event}}" from "{{Name}}"`,
|
Subject: `New "{{Event}}" from "{{Name}}" status {{StatusString}}`,
|
||||||
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} Data: {{ObjectData}}",
|
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} Data: {{ObjectData}} {{ErrorString}}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -3076,7 +3077,7 @@ func TestEventRule(t *testing.T) {
|
||||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||||
Recipients: []string{"failure@example.com"},
|
Recipients: []string{"failure@example.com"},
|
||||||
Subject: `Failed "{{Event}}" from "{{Name}}"`,
|
Subject: `Failed "{{Event}}" from "{{Name}}"`,
|
||||||
Body: "Fs path {{FsPath}}, protocol: {{Protocol}}, IP: {{IP}}",
|
Body: "Fs path {{FsPath}}, protocol: {{Protocol}}, IP: {{IP}} {{ErrorString}}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -3187,6 +3188,7 @@ func TestEventRule(t *testing.T) {
|
||||||
|
|
||||||
uploadScriptPath := filepath.Join(os.TempDir(), "upload.sh")
|
uploadScriptPath := filepath.Join(os.TempDir(), "upload.sh")
|
||||||
u := getTestUser()
|
u := getTestUser()
|
||||||
|
u.DownloadDataTransfer = 1
|
||||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
movedFileName := "moved.dat"
|
movedFileName := "moved.dat"
|
||||||
|
@ -3230,6 +3232,8 @@ func TestEventRule(t *testing.T) {
|
||||||
dirName := "subdir"
|
dirName := "subdir"
|
||||||
err = client.Mkdir(dirName)
|
err = client.Mkdir(dirName)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
err = client.Mkdir("subdir1")
|
||||||
|
assert.NoError(t, err)
|
||||||
// rule conditions match
|
// rule conditions match
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
err = writeSFTPFileNoCheck(path.Join(dirName, testFileName), size, client)
|
err = writeSFTPFileNoCheck(path.Join(dirName, testFileName), size, client)
|
||||||
|
@ -3247,7 +3251,32 @@ func TestEventRule(t *testing.T) {
|
||||||
assert.Len(t, email.To, 2)
|
assert.Len(t, email.To, 2)
|
||||||
assert.True(t, util.Contains(email.To, "test1@example.com"))
|
assert.True(t, util.Contains(email.To, "test1@example.com"))
|
||||||
assert.True(t, util.Contains(email.To, "test2@example.com"))
|
assert.True(t, util.Contains(email.To, "test2@example.com"))
|
||||||
assert.Contains(t, string(email.Data), fmt.Sprintf(`Subject: New "upload" from "%s"`, user.Username))
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: New "upload" from "%s" status OK`, user.Username))
|
||||||
|
// test the failure action, we download a file that exceeds the transfer quota limit
|
||||||
|
err = writeSFTPFileNoCheck(path.Join("subdir1", testFileName), 1*1024*1024+65535, client)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
lastReceivedEmail.reset()
|
||||||
|
f, err := client.Open(path.Join("subdir1", testFileName))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = io.ReadAll(f)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.Contains(t, err.Error(), common.ErrReadQuotaExceeded.Error())
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Eventually(t, func() bool {
|
||||||
|
return lastReceivedEmail.get().From != ""
|
||||||
|
}, 3000*time.Millisecond, 100*time.Millisecond)
|
||||||
|
email = lastReceivedEmail.get()
|
||||||
|
assert.Len(t, email.To, 2)
|
||||||
|
assert.True(t, util.Contains(email.To, "test1@example.com"))
|
||||||
|
assert.True(t, util.Contains(email.To, "test2@example.com"))
|
||||||
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: New "download" from "%s" status KO`, user.Username))
|
||||||
|
assert.Contains(t, email.Data, `"download" failed`)
|
||||||
|
assert.Contains(t, email.Data, common.ErrReadQuotaExceeded.Error())
|
||||||
|
_, err = httpdtest.UpdateTransferQuotaUsage(user, "", http.StatusOK)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// remove the upload script to test the failure action
|
// remove the upload script to test the failure action
|
||||||
err = os.Remove(uploadScriptPath)
|
err = os.Remove(uploadScriptPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -3260,10 +3289,11 @@ func TestEventRule(t *testing.T) {
|
||||||
email = lastReceivedEmail.get()
|
email = lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "failure@example.com"))
|
assert.True(t, util.Contains(email.To, "failure@example.com"))
|
||||||
assert.Contains(t, string(email.Data), fmt.Sprintf(`Subject: Failed "upload" from "%s"`, user.Username))
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: Failed "upload" from "%s"`, user.Username))
|
||||||
|
assert.Contains(t, email.Data, fmt.Sprintf(`action %q failed`, action1.Name))
|
||||||
// now test the download rule
|
// now test the download rule
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
f, err := client.Open(movedFileName)
|
f, err = client.Open(movedFileName)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
contents, err := io.ReadAll(f)
|
contents, err := io.ReadAll(f)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -3277,7 +3307,7 @@ func TestEventRule(t *testing.T) {
|
||||||
assert.Len(t, email.To, 2)
|
assert.Len(t, email.To, 2)
|
||||||
assert.True(t, util.Contains(email.To, "test1@example.com"))
|
assert.True(t, util.Contains(email.To, "test1@example.com"))
|
||||||
assert.True(t, util.Contains(email.To, "test2@example.com"))
|
assert.True(t, util.Contains(email.To, "test2@example.com"))
|
||||||
assert.Contains(t, string(email.Data), fmt.Sprintf(`Subject: New "download" from "%s"`, user.Username))
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: New "download" from "%s"`, user.Username))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
|
_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
|
||||||
|
@ -3291,7 +3321,7 @@ func TestEventRule(t *testing.T) {
|
||||||
assert.Len(t, email.To, 2)
|
assert.Len(t, email.To, 2)
|
||||||
assert.True(t, util.Contains(email.To, "test1@example.com"))
|
assert.True(t, util.Contains(email.To, "test1@example.com"))
|
||||||
assert.True(t, util.Contains(email.To, "test2@example.com"))
|
assert.True(t, util.Contains(email.To, "test2@example.com"))
|
||||||
assert.Contains(t, string(email.Data), `Subject: New "delete" from "admin"`)
|
assert.Contains(t, email.Data, `Subject: New "delete" from "admin"`)
|
||||||
_, err = httpdtest.RemoveEventRule(rule3, http.StatusOK)
|
_, err = httpdtest.RemoveEventRule(rule3, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
|
_, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
|
||||||
|
@ -3443,7 +3473,7 @@ func TestEventRuleProviderEvents(t *testing.T) {
|
||||||
email := lastReceivedEmail.get()
|
email := lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "test3@example.com"))
|
assert.True(t, util.Contains(email.To, "test3@example.com"))
|
||||||
assert.Contains(t, string(email.Data), `Subject: New "update" from "admin"`)
|
assert.Contains(t, email.Data, `Subject: New "update" from "admin"`)
|
||||||
}
|
}
|
||||||
// now delete the script to generate an error
|
// now delete the script to generate an error
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
|
@ -3458,8 +3488,8 @@ func TestEventRuleProviderEvents(t *testing.T) {
|
||||||
email := lastReceivedEmail.get()
|
email := lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "failure@example.com"))
|
assert.True(t, util.Contains(email.To, "failure@example.com"))
|
||||||
assert.Contains(t, string(email.Data), `Subject: Failed "update" from "admin"`)
|
assert.Contains(t, email.Data, `Subject: Failed "update" from "admin"`)
|
||||||
assert.Contains(t, string(email.Data), fmt.Sprintf("Object name: %s object type: folder", folder.Name))
|
assert.Contains(t, email.Data, fmt.Sprintf("Object name: %s object type: folder", folder.Name))
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
// generate an error for the failure action
|
// generate an error for the failure action
|
||||||
smtpCfg = smtp.Config{}
|
smtpCfg = smtp.Config{}
|
||||||
|
@ -3830,8 +3860,8 @@ func TestEventActionEmailAttachments(t *testing.T) {
|
||||||
email := lastReceivedEmail.get()
|
email := lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "test@example.com"))
|
assert.True(t, util.Contains(email.To, "test@example.com"))
|
||||||
assert.Contains(t, string(email.Data), fmt.Sprintf(`Subject: "upload" from "%s"`, user.Username))
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "upload" from "%s"`, user.Username))
|
||||||
assert.Contains(t, string(email.Data), "Content-Disposition: attachment")
|
assert.Contains(t, email.Data, "Content-Disposition: attachment")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3929,7 +3959,7 @@ func TestEventRuleFirstUploadDownloadActions(t *testing.T) {
|
||||||
email := lastReceivedEmail.get()
|
email := lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "test@example.com"))
|
assert.True(t, util.Contains(email.To, "test@example.com"))
|
||||||
assert.Contains(t, string(email.Data), fmt.Sprintf(`Subject: "first-upload" from "%s"`, user.Username))
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "first-upload" from "%s"`, user.Username))
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
// a new upload will not produce a new notification
|
// a new upload will not produce a new notification
|
||||||
err = writeSFTPFileNoCheck(testFileName+"_1", 32768, client)
|
err = writeSFTPFileNoCheck(testFileName+"_1", 32768, client)
|
||||||
|
@ -3952,7 +3982,7 @@ func TestEventRuleFirstUploadDownloadActions(t *testing.T) {
|
||||||
email = lastReceivedEmail.get()
|
email = lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "test@example.com"))
|
assert.True(t, util.Contains(email.To, "test@example.com"))
|
||||||
assert.Contains(t, string(email.Data), fmt.Sprintf(`Subject: "first-download" from "%s"`, user.Username))
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "first-download" from "%s"`, user.Username))
|
||||||
// download again
|
// download again
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
f, err = client.Open(testFileName)
|
f, err = client.Open(testFileName)
|
||||||
|
@ -4001,8 +4031,8 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
Options: dataprovider.BaseEventActionOptions{
|
Options: dataprovider.BaseEventActionOptions{
|
||||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||||
Recipients: []string{"test@example.com"},
|
Recipients: []string{"test@example.com"},
|
||||||
Subject: `"{{Event}}"`,
|
Subject: `"{{Event}} {{StatusString}}"`,
|
||||||
Body: "Domain: {{Name}} Timestamp: {{Timestamp}}",
|
Body: "Domain: {{Name}} Timestamp: {{Timestamp}} {{ErrorString}}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -4051,11 +4081,13 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
rule2, _, err := httpdtest.AddEventRule(r2, http.StatusCreated)
|
rule2, _, err := httpdtest.AddEventRule(r2, http.StatusCreated)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
renewalEvent := "Certificate renewal"
|
||||||
|
|
||||||
common.HandleCertificateEvent(common.EventParams{
|
common.HandleCertificateEvent(common.EventParams{
|
||||||
Name: "example.com",
|
Name: "example.com",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().UnixNano(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
Event: "Successful certificate renewal",
|
Event: renewalEvent,
|
||||||
})
|
})
|
||||||
assert.Eventually(t, func() bool {
|
assert.Eventually(t, func() bool {
|
||||||
return lastReceivedEmail.get().From != ""
|
return lastReceivedEmail.get().From != ""
|
||||||
|
@ -4063,24 +4095,28 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
email := lastReceivedEmail.get()
|
email := lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "test@example.com"))
|
assert.True(t, util.Contains(email.To, "test@example.com"))
|
||||||
assert.Contains(t, string(email.Data), `Subject: "Successful certificate renewal"`)
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "%s OK"`, renewalEvent))
|
||||||
assert.Contains(t, string(email.Data), `Domain: example.com Timestamp`)
|
assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
|
||||||
|
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
common.HandleCertificateEvent(common.EventParams{
|
params := common.EventParams{
|
||||||
Name: "example.com",
|
Name: "example.com",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().UnixNano(),
|
||||||
Status: 2,
|
Status: 2,
|
||||||
Event: "Certificate renewal failed",
|
Event: renewalEvent,
|
||||||
})
|
}
|
||||||
|
errRenew := errors.New("generic renew error")
|
||||||
|
params.AddError(errRenew)
|
||||||
|
common.HandleCertificateEvent(params)
|
||||||
assert.Eventually(t, func() bool {
|
assert.Eventually(t, func() bool {
|
||||||
return lastReceivedEmail.get().From != ""
|
return lastReceivedEmail.get().From != ""
|
||||||
}, 3000*time.Millisecond, 100*time.Millisecond)
|
}, 3000*time.Millisecond, 100*time.Millisecond)
|
||||||
email = lastReceivedEmail.get()
|
email = lastReceivedEmail.get()
|
||||||
assert.Len(t, email.To, 1)
|
assert.Len(t, email.To, 1)
|
||||||
assert.True(t, util.Contains(email.To, "test@example.com"))
|
assert.True(t, util.Contains(email.To, "test@example.com"))
|
||||||
assert.Contains(t, string(email.Data), `Subject: "Certificate renewal failed"`)
|
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "%s KO"`, renewalEvent))
|
||||||
assert.Contains(t, string(email.Data), `Domain: example.com Timestamp`)
|
assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
|
||||||
|
assert.Contains(t, email.Data, errRenew.Error())
|
||||||
|
|
||||||
_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
|
_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -4095,7 +4131,7 @@ func TestEventRuleCertificate(t *testing.T) {
|
||||||
Name: "example.com",
|
Name: "example.com",
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().UnixNano(),
|
||||||
Status: 1,
|
Status: 1,
|
||||||
Event: "Successful certificate renewal",
|
Event: renewalEvent,
|
||||||
})
|
})
|
||||||
|
|
||||||
smtpCfg = smtp.Config{}
|
smtpCfg = smtp.Config{}
|
||||||
|
@ -4184,7 +4220,7 @@ func TestEventRuleIPBlocked(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
lastReceivedEmail.reset()
|
lastReceivedEmail.reset()
|
||||||
time.Sleep(300 * time.Millisecond)
|
time.Sleep(300 * time.Millisecond)
|
||||||
assert.Empty(t, lastReceivedEmail.get().From, string(lastReceivedEmail.get().Data))
|
assert.Empty(t, lastReceivedEmail.get().From, lastReceivedEmail.get().Data)
|
||||||
|
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
user.Password = "wrong_pwd"
|
user.Password = "wrong_pwd"
|
||||||
|
@ -4203,7 +4239,7 @@ func TestEventRuleIPBlocked(t *testing.T) {
|
||||||
assert.Len(t, email.To, 2)
|
assert.Len(t, email.To, 2)
|
||||||
assert.True(t, util.Contains(email.To, "test3@example.com"))
|
assert.True(t, util.Contains(email.To, "test3@example.com"))
|
||||||
assert.True(t, util.Contains(email.To, "test4@example.com"))
|
assert.True(t, util.Contains(email.To, "test4@example.com"))
|
||||||
assert.Contains(t, string(email.Data), `Subject: New "IP Blocked"`)
|
assert.Contains(t, email.Data, `Subject: New "IP Blocked"`)
|
||||||
|
|
||||||
err = dataprovider.DeleteEventRule(rule1.Name, "", "")
|
err = dataprovider.DeleteEventRule(rule1.Name, "", "")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -5305,7 +5341,7 @@ type receivedEmail struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
From string
|
From string
|
||||||
To []string
|
To []string
|
||||||
Data []byte
|
Data string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *receivedEmail) set(from string, to []string, data []byte) {
|
func (e *receivedEmail) set(from string, to []string, data []byte) {
|
||||||
|
@ -5314,7 +5350,7 @@ func (e *receivedEmail) set(from string, to []string, data []byte) {
|
||||||
|
|
||||||
e.From = from
|
e.From = from
|
||||||
e.To = to
|
e.To = to
|
||||||
e.Data = data
|
e.Data = strings.ReplaceAll(string(data), "=\r\n", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *receivedEmail) reset() {
|
func (e *receivedEmail) reset() {
|
||||||
|
@ -5323,7 +5359,7 @@ func (e *receivedEmail) reset() {
|
||||||
|
|
||||||
e.From = ""
|
e.From = ""
|
||||||
e.To = nil
|
e.To = nil
|
||||||
e.Data = nil
|
e.Data = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *receivedEmail) get() receivedEmail {
|
func (e *receivedEmail) get() receivedEmail {
|
||||||
|
|
|
@ -541,6 +541,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
<p>
|
<p>
|
||||||
<span class="shortcut"><b>{{`{{Status}}`}}</b></span> => Status for "upload", "download" and "ssh_cmd" events. 1 means no error, 2 means a generic error occurred, 3 means quota exceeded error.
|
<span class="shortcut"><b>{{`{{Status}}`}}</b></span> => Status for "upload", "download" and "ssh_cmd" events. 1 means no error, 2 means a generic error occurred, 3 means quota exceeded error.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="shortcut"><b>{{`{{StatusString}}`}}</b></span> => Status as string. Possible values "OK", "KO".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="shortcut"><b>{{`{{ErrorString}}`}}</b></span> => Error details. Replaced with an empty string if no errors occur.
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="shortcut"><b>{{`{{VirtualPath}}`}}</b></span> => Path seen by SFTPGo users, for example "/adir/afile.txt".
|
<span class="shortcut"><b>{{`{{VirtualPath}}`}}</b></span> => Path seen by SFTPGo users, for example "/adir/afile.txt".
|
||||||
</p>
|
</p>
|
||||||
|
|
Loading…
Reference in a new issue