mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-22 07:30:25 +00:00
allow to disable event rules
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
496c8bc785
commit
53f17b5715
24 changed files with 342 additions and 62 deletions
10
go.mod
10
go.mod
|
@ -56,7 +56,7 @@ require (
|
|||
github.com/shirou/gopsutil/v3 v3.22.12
|
||||
github.com/spf13/afero v1.9.3
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/viper v1.14.0
|
||||
github.com/spf13/viper v1.15.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/studio-b12/gowebdav v0.0.0-20221109171924-60ec5ad56012
|
||||
github.com/subosito/gotenv v1.4.2
|
||||
|
@ -73,12 +73,12 @@ require (
|
|||
golang.org/x/sys v0.4.0
|
||||
golang.org/x/term v0.4.0
|
||||
golang.org/x/time v0.3.0
|
||||
google.golang.org/api v0.107.0
|
||||
google.golang.org/api v0.108.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.108.0 // indirect
|
||||
cloud.google.com/go v0.109.0 // indirect
|
||||
cloud.google.com/go/compute v1.15.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v0.10.0 // indirect
|
||||
|
@ -138,7 +138,6 @@ require (
|
|||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
|
@ -158,11 +157,10 @@ require (
|
|||
golang.org/x/tools v0.5.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230117162540-28d6b9783ac4 // indirect
|
||||
google.golang.org/grpc v1.52.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
|
|
18
go.sum
18
go.sum
|
@ -37,8 +37,8 @@ cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34h
|
|||
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
|
||||
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||
cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
|
||||
cloud.google.com/go v0.108.0 h1:xntQwnfn8oHGX0crLVinvHM+AhXvi3QHQIEcX/2hiWk=
|
||||
cloud.google.com/go v0.108.0/go.mod h1:lNUfQqusBJp0bgAg6qrHgYFYbTB+dOiob1itwnlD33Q=
|
||||
cloud.google.com/go v0.109.0 h1:38CZoKGlCnPZjGdyj0ZfpoGae0/wgNfy5F0byyxg0Gk=
|
||||
cloud.google.com/go v0.109.0/go.mod h1:2sYycXt75t/CSB5R9M2wPU1tJmire7AQZTPtITcGBVE=
|
||||
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
|
||||
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
|
||||
cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o=
|
||||
|
@ -1663,8 +1663,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
|
|||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
|
@ -1856,8 +1854,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
|
||||
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
|
||||
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
|
@ -2577,8 +2575,8 @@ google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91
|
|||
google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
|
||||
google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
|
||||
google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0=
|
||||
google.golang.org/api v0.107.0 h1:I2SlFjD8ZWabaIFOfeEDg3pf0BHJDh6iYQ1ic3Yu/UU=
|
||||
google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
||||
google.golang.org/api v0.108.0 h1:WVBc/faN0DkKtR43Q/7+tPny9ZoLZdIiAyG5Q9vFClg=
|
||||
google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
@ -2712,8 +2710,8 @@ google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZV
|
|||
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5 h1:wJT65XLOzhpSPCdAmmKfz94SlmnQzDzjm3Cj9k3fsXY=
|
||||
google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230117162540-28d6b9783ac4 h1:yF0uHwqqYt2tIL2F4hxRWA1ZFX43SEunWAK8MnQiclk=
|
||||
google.golang.org/genproto v0.0.0-20230117162540-28d6b9783ac4/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
|
|
@ -949,7 +949,7 @@ func (conns *ActiveConnections) Remove(connectionID string) {
|
|||
return
|
||||
}
|
||||
|
||||
logger.Warn(logSender, "", "connection id %q to remove not found!", connectionID)
|
||||
logger.Debug(logSender, "", "connection id %q to remove not found!", connectionID)
|
||||
}
|
||||
|
||||
// Close closes an active connection.
|
||||
|
|
|
@ -197,6 +197,9 @@ func (r *eventRulesContainer) addUpdateRuleInternal(rule dataprovider.EventRule)
|
|||
}
|
||||
return
|
||||
}
|
||||
if rule.Status != 1 {
|
||||
return
|
||||
}
|
||||
switch rule.Trigger {
|
||||
case dataprovider.EventTriggerFsEvent:
|
||||
r.FsEvents = append(r.FsEvents, rule)
|
||||
|
|
|
@ -320,6 +320,7 @@ func TestEventManager(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
rule := &dataprovider.EventRule{
|
||||
Name: "rule",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{operationUpload},
|
||||
|
@ -595,6 +596,7 @@ func TestEventManagerErrors(t *testing.T) {
|
|||
// rule with invalid trigger
|
||||
eventManager.addUpdateRuleInternal(dataprovider.EventRule{
|
||||
Name: "test rule",
|
||||
Status: 1,
|
||||
Trigger: -1,
|
||||
})
|
||||
|
||||
|
@ -606,6 +608,7 @@ func TestEventManagerErrors(t *testing.T) {
|
|||
// rule with invalid cronspec
|
||||
eventManager.addUpdateRuleInternal(dataprovider.EventRule{
|
||||
Name: "test rule",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerSchedule,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
Schedules: []dataprovider.Schedule{
|
||||
|
@ -1602,6 +1605,7 @@ func TestScheduledActions(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
rule := &dataprovider.EventRule{
|
||||
Name: "rule",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerSchedule,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
Schedules: []dataprovider.Schedule{
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -3461,6 +3462,7 @@ func TestEventRule(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -3514,6 +3516,7 @@ func TestEventRule(t *testing.T) {
|
|||
|
||||
r2 := dataprovider.EventRule{
|
||||
Name: "test rule2",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"download"},
|
||||
|
@ -3548,6 +3551,7 @@ func TestEventRule(t *testing.T) {
|
|||
|
||||
r3 := dataprovider.EventRule{
|
||||
Name: "test rule3",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerProviderEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
ProviderEvents: []string{"delete"},
|
||||
|
@ -3810,6 +3814,7 @@ func TestEventRuleProviderEvents(t *testing.T) {
|
|||
|
||||
r := dataprovider.EventRule{
|
||||
Name: "rule",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerProviderEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
ProviderEvents: []string{"update"},
|
||||
|
@ -3991,6 +3996,7 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "r1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerProviderEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
ProviderEvents: []string{"add"},
|
||||
|
@ -4006,6 +4012,7 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
}
|
||||
r2 := dataprovider.EventRule{
|
||||
Name: "r2",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -4030,6 +4037,7 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
}
|
||||
r3 := dataprovider.EventRule{
|
||||
Name: "r3",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"mkdir"},
|
||||
|
@ -4051,6 +4059,7 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
}
|
||||
r4 := dataprovider.EventRule{
|
||||
Name: "r4",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"rmdir"},
|
||||
|
@ -4066,6 +4075,7 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
}
|
||||
r5 := dataprovider.EventRule{
|
||||
Name: "r5",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerProviderEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
ProviderEvents: []string{"add"},
|
||||
|
@ -4216,6 +4226,7 @@ func TestEventRulePreDelete(t *testing.T) {
|
|||
assert.NoError(t, err, string(resp))
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"pre-delete"},
|
||||
|
@ -4347,6 +4358,7 @@ func TestEventRulePreDownloadUpload(t *testing.T) {
|
|||
assert.NoError(t, err, string(resp))
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"pre-download", "pre-upload"},
|
||||
|
@ -4386,7 +4398,20 @@ func TestEventRulePreDownloadUpload(t *testing.T) {
|
|||
assert.Equal(t, int(100), n)
|
||||
err = f.Close()
|
||||
assert.NoError(t, err)
|
||||
// disable the rule
|
||||
rule1.Status = 0
|
||||
_, _, err = httpdtest.UpdateEventRule(rule1, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
err = client.RemoveDirectory(testDir)
|
||||
assert.NoError(t, err)
|
||||
err = client.Remove(testFileName)
|
||||
assert.NoError(t, err)
|
||||
err = writeSFTPFile(testFileName, 100, client)
|
||||
assert.NoError(t, err)
|
||||
_, err = client.Stat(testDir)
|
||||
assert.ErrorIs(t, err, fs.ErrNotExist)
|
||||
// now update the rule so that it will always fail
|
||||
rule1.Status = 1
|
||||
rule1.Actions = []dataprovider.EventAction{
|
||||
{
|
||||
BaseEventAction: dataprovider.BaseEventAction{
|
||||
|
@ -4441,6 +4466,7 @@ func TestFsActionCopy(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -4520,6 +4546,7 @@ func TestEventFsActionsGroupFilters(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -4657,6 +4684,7 @@ func TestBackupAsAttachment(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test rule certificate",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerCertificate,
|
||||
Actions: []dataprovider.EventAction{
|
||||
{
|
||||
|
@ -4738,6 +4766,7 @@ func TestEventActionHTTPMultipart(t *testing.T) {
|
|||
assert.NoError(t, err, string(resp))
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test http multipart",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -4813,6 +4842,7 @@ func TestEventActionCompress(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test compress",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -4981,6 +5011,7 @@ func TestEventActionCompressQuotaErrors(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test compress",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"rename"},
|
||||
|
@ -5126,6 +5157,7 @@ func TestEventActionCompressQuotaFolder(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test compress",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -5246,6 +5278,7 @@ func TestEventActionCompressErrors(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test compress",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -5383,6 +5416,7 @@ func TestEventActionEmailAttachments(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test email with attachment",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -5536,6 +5570,7 @@ func TestEventActionsRetentionReports(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload"},
|
||||
|
@ -5729,6 +5764,7 @@ func TestEventRuleFirstUploadDownloadActions(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test first upload rule",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"first-upload"},
|
||||
|
@ -5746,6 +5782,7 @@ func TestEventRuleFirstUploadDownloadActions(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r2 := dataprovider.EventRule{
|
||||
Name: "test first download rule",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"first-download"},
|
||||
|
@ -5859,6 +5896,7 @@ func TestEventRuleRenameEvent(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test rename rule",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"rename"},
|
||||
|
@ -5948,6 +5986,7 @@ func TestEventRuleCertificate(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test rule certificate",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerCertificate,
|
||||
Actions: []dataprovider.EventAction{
|
||||
{
|
||||
|
@ -5962,6 +6001,7 @@ func TestEventRuleCertificate(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r2 := dataprovider.EventRule{
|
||||
Name: "test rule 2",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerCertificate,
|
||||
Actions: []dataprovider.EventAction{
|
||||
{
|
||||
|
@ -6082,6 +6122,7 @@ func TestEventRuleIPBlocked(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "test rule ip blocked",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerIPBlocked,
|
||||
Actions: []dataprovider.EventAction{
|
||||
{
|
||||
|
@ -6096,6 +6137,7 @@ func TestEventRuleIPBlocked(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r2 := dataprovider.EventRule{
|
||||
Name: "test rule 2",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerIPBlocked,
|
||||
Actions: []dataprovider.EventAction{
|
||||
{
|
||||
|
@ -6214,6 +6256,7 @@ func TestEventRulePasswordExpiration(t *testing.T) {
|
|||
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
FsEvents: []string{"mkdir"},
|
||||
|
@ -7017,6 +7060,7 @@ func TestSFTPLoopError(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
r1 := dataprovider.EventRule{
|
||||
Name: "rule1",
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerProviderEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
ProviderEvents: []string{"update"},
|
||||
|
|
|
@ -35,7 +35,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
boltDatabaseVersion = 25
|
||||
boltDatabaseVersion = 26
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -2833,10 +2833,41 @@ func (p *BoltProvider) migrateDatabase() error {
|
|||
providerLog(logger.LevelError, "%v", err)
|
||||
logger.ErrorToConsole("%v", err)
|
||||
return err
|
||||
case version == 23, version == 24:
|
||||
logger.InfoToConsole(fmt.Sprintf("updating database schema version: %d -> 25", version))
|
||||
providerLog(logger.LevelInfo, "updating database schema version: %d -> 25", version)
|
||||
return updateBoltDatabaseVersion(p.dbHandle, 25)
|
||||
case version == 23, version == 24, version == 25:
|
||||
logger.InfoToConsole("updating database schema version: %d -> 26", version)
|
||||
providerLog(logger.LevelInfo, "updating database schema version: %d -> 26", version)
|
||||
err := p.dbHandle.Update(func(tx *bolt.Tx) error {
|
||||
rules, err := p.dumpEventRules()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bucket, err := p.getRulesBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, rule := range rules {
|
||||
rule := rule // pin
|
||||
if rule.Status == 1 {
|
||||
continue
|
||||
}
|
||||
logger.InfoToConsole("setting status to active for rule %q", rule.Name)
|
||||
providerLog(logger.LevelInfo, "setting status to 1 for rule %q", rule.Name)
|
||||
rule.Status = 1
|
||||
rule.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
|
||||
buf, err := json.Marshal(rule)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bucket.Put([]byte(rule.Name), buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return updateBoltDatabaseVersion(p.dbHandle, 26)
|
||||
default:
|
||||
if version > boltDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
@ -2858,7 +2889,7 @@ func (p *BoltProvider) revertDatabase(targetVersion int) error {
|
|||
return errors.New("current version match target version, nothing to do")
|
||||
}
|
||||
switch dbVersion.Version {
|
||||
case 24, 25:
|
||||
case 24, 25, 26:
|
||||
logger.InfoToConsole("downgrading database schema version: %d -> 23", dbVersion.Version)
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: %d -> 23", dbVersion.Version)
|
||||
err := p.dbHandle.Update(func(tx *bolt.Tx) error {
|
||||
|
|
|
@ -87,7 +87,7 @@ const (
|
|||
CockroachDataProviderName = "cockroachdb"
|
||||
// DumpVersion defines the version for the dump.
|
||||
// For restore/load we support the current version and the previous one
|
||||
DumpVersion = 14
|
||||
DumpVersion = 15
|
||||
|
||||
argonPwdPrefix = "$argon2id$"
|
||||
bcryptPwdPrefix = "$2a$"
|
||||
|
|
|
@ -1313,6 +1313,8 @@ type EventRule struct {
|
|||
ID int64 `json:"id"`
|
||||
// Rule name
|
||||
Name string `json:"name"`
|
||||
// 1 enabled, 0 disabled
|
||||
Status int `json:"status"`
|
||||
// optional description
|
||||
Description string `json:"description,omitempty"`
|
||||
// Creation time as unix timestamp in milliseconds
|
||||
|
@ -1338,6 +1340,7 @@ func (r *EventRule) getACopy() EventRule {
|
|||
return EventRule{
|
||||
ID: r.ID,
|
||||
Name: r.Name,
|
||||
Status: r.Status,
|
||||
Description: r.Description,
|
||||
CreatedAt: r.CreatedAt,
|
||||
UpdatedAt: r.UpdatedAt,
|
||||
|
@ -1371,10 +1374,17 @@ func (r *EventRule) GetActionsAsString() string {
|
|||
return strings.Join(actions, ",")
|
||||
}
|
||||
|
||||
func (r *EventRule) isStatusValid() bool {
|
||||
return r.Status >= 0 && r.Status <= 1
|
||||
}
|
||||
|
||||
func (r *EventRule) validate() error {
|
||||
if r.Name == "" {
|
||||
return util.NewValidationError("name is mandatory")
|
||||
}
|
||||
if !r.isStatusValid() {
|
||||
return util.NewValidationError(fmt.Sprintf("invalid event rule status: %d", r.Status))
|
||||
}
|
||||
if !isEventTriggerValid(r.Trigger) {
|
||||
return util.NewValidationError(fmt.Sprintf("invalid event rule trigger: %d", r.Trigger))
|
||||
}
|
||||
|
|
|
@ -2825,6 +2825,9 @@ func (p *MemoryProvider) restoreEventRules(dump BackupData) error {
|
|||
for _, rule := range dump.EventRules {
|
||||
r, err := p.eventRuleExists(rule.Name)
|
||||
rule := rule // pin
|
||||
if dump.Version < 15 {
|
||||
rule.Status = 1
|
||||
}
|
||||
if err == nil {
|
||||
rule.ID = r.ID
|
||||
err = UpdateEventRule(&rule, ActionExecutorSystem, "", "")
|
||||
|
|
|
@ -186,6 +186,9 @@ const (
|
|||
mysqlV25SQL = "ALTER TABLE `{{users}}` ADD COLUMN `last_password_change` bigint DEFAULT 0 NOT NULL; " +
|
||||
"ALTER TABLE `{{users}}` ALTER COLUMN `last_password_change` DROP DEFAULT; "
|
||||
mysqlV25DownSQL = "ALTER TABLE `{{users}}` DROP COLUMN `last_password_change`; "
|
||||
mysqlV26SQL = "ALTER TABLE `{{events_rules}}` ADD COLUMN `status` integer DEFAULT 1 NOT NULL; " +
|
||||
"ALTER TABLE `{{events_rules}}` ALTER COLUMN `status` DROP DEFAULT; "
|
||||
mysqlV26DownSQL = "ALTER TABLE `{{events_rules}}` DROP COLUMN `status`; "
|
||||
)
|
||||
|
||||
// MySQLProvider defines the auth provider for MySQL/MariaDB database
|
||||
|
@ -744,6 +747,8 @@ func (p *MySQLProvider) migrateDatabase() error { //nolint:dupl
|
|||
return updateMySQLDatabaseFromV23(p.dbHandle)
|
||||
case version == 24:
|
||||
return updateMySQLDatabaseFromV24(p.dbHandle)
|
||||
case version == 25:
|
||||
return updateMySQLDatabaseFromV25(p.dbHandle)
|
||||
default:
|
||||
if version > sqlDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
@ -770,6 +775,8 @@ func (p *MySQLProvider) revertDatabase(targetVersion int) error {
|
|||
return downgradeMySQLDatabaseFromV24(p.dbHandle)
|
||||
case 25:
|
||||
return downgradeMySQLDatabaseFromV25(p.dbHandle)
|
||||
case 26:
|
||||
return downgradeMySQLDatabaseFromV26(p.dbHandle)
|
||||
default:
|
||||
return fmt.Errorf("database schema version not handled: %d", dbVersion.Version)
|
||||
}
|
||||
|
@ -788,7 +795,14 @@ func updateMySQLDatabaseFromV23(dbHandle *sql.DB) error {
|
|||
}
|
||||
|
||||
func updateMySQLDatabaseFromV24(dbHandle *sql.DB) error {
|
||||
return updateMySQLDatabaseFrom24To25(dbHandle)
|
||||
if err := updateMySQLDatabaseFrom24To25(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updateMySQLDatabaseFromV25(dbHandle)
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFromV25(dbHandle *sql.DB) error {
|
||||
return updateMySQLDatabaseFrom25To26(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFromV24(dbHandle *sql.DB) error {
|
||||
|
@ -802,6 +816,13 @@ func downgradeMySQLDatabaseFromV25(dbHandle *sql.DB) error {
|
|||
return downgradeMySQLDatabaseFromV24(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFromV26(dbHandle *sql.DB) error {
|
||||
if err := downgradeMySQLDatabaseFrom26To25(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradeMySQLDatabaseFromV25(dbHandle)
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFrom23To24(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 23 -> 24")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 23 -> 24")
|
||||
|
@ -819,6 +840,13 @@ func updateMySQLDatabaseFrom24To25(dbHandle *sql.DB) error {
|
|||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 25, true)
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFrom25To26(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 25 -> 26")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 25 -> 26")
|
||||
sql := strings.ReplaceAll(mysqlV26SQL, "{{events_rules}}", sqlTableEventsRules)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 26, true)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFrom24To23(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 24 -> 23")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 24 -> 23")
|
||||
|
@ -835,3 +863,10 @@ func downgradeMySQLDatabaseFrom25To24(dbHandle *sql.DB) error {
|
|||
sql := strings.ReplaceAll(mysqlV25DownSQL, "{{users}}", sqlTableUsers)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 24, false)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFrom26To25(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 26 -> 25")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 26 -> 25")
|
||||
sql := strings.ReplaceAll(mysqlV26DownSQL, "{{events_rules}}", sqlTableEventsRules)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 25, false)
|
||||
}
|
||||
|
|
|
@ -198,6 +198,10 @@ DROP TABLE "{{roles}}" CASCADE;
|
|||
ALTER TABLE "{{users}}" ALTER COLUMN "last_password_change" DROP DEFAULT;
|
||||
`
|
||||
pgsqlV25DownSQL = `ALTER TABLE "{{users}}" DROP COLUMN "last_password_change" CASCADE;`
|
||||
pgsqlV26SQL = `ALTER TABLE "{{events_rules}}" ADD COLUMN "status" integer DEFAULT 1 NOT NULL;
|
||||
ALTER TABLE "{{events_rules}}" ALTER COLUMN "status" DROP DEFAULT;
|
||||
`
|
||||
pgsqlV26DownSQL = `ALTER TABLE "{{events_rules}}" DROP COLUMN "status" CASCADE;`
|
||||
)
|
||||
|
||||
// PGSQLProvider defines the auth provider for PostgreSQL database
|
||||
|
@ -715,6 +719,8 @@ func (p *PGSQLProvider) migrateDatabase() error { //nolint:dupl
|
|||
return updatePgSQLDatabaseFromV23(p.dbHandle)
|
||||
case version == 24:
|
||||
return updatePgSQLDatabaseFromV24(p.dbHandle)
|
||||
case version == 25:
|
||||
return updatePgSQLDatabaseFromV25(p.dbHandle)
|
||||
default:
|
||||
if version > sqlDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
@ -741,6 +747,8 @@ func (p *PGSQLProvider) revertDatabase(targetVersion int) error {
|
|||
return downgradePgSQLDatabaseFromV24(p.dbHandle)
|
||||
case 25:
|
||||
return downgradePgSQLDatabaseFromV25(p.dbHandle)
|
||||
case 26:
|
||||
return downgradePgSQLDatabaseFromV26(p.dbHandle)
|
||||
default:
|
||||
return fmt.Errorf("database schema version not handled: %d", dbVersion.Version)
|
||||
}
|
||||
|
@ -759,7 +767,14 @@ func updatePgSQLDatabaseFromV23(dbHandle *sql.DB) error {
|
|||
}
|
||||
|
||||
func updatePgSQLDatabaseFromV24(dbHandle *sql.DB) error {
|
||||
return updatePgSQLDatabaseFrom24To25(dbHandle)
|
||||
if err := updatePgSQLDatabaseFrom24To25(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updatePgSQLDatabaseFromV25(dbHandle)
|
||||
}
|
||||
|
||||
func updatePgSQLDatabaseFromV25(dbHandle *sql.DB) error {
|
||||
return updatePgSQLDatabaseFrom25To26(dbHandle)
|
||||
}
|
||||
|
||||
func downgradePgSQLDatabaseFromV24(dbHandle *sql.DB) error {
|
||||
|
@ -773,6 +788,13 @@ func downgradePgSQLDatabaseFromV25(dbHandle *sql.DB) error {
|
|||
return downgradePgSQLDatabaseFromV24(dbHandle)
|
||||
}
|
||||
|
||||
func downgradePgSQLDatabaseFromV26(dbHandle *sql.DB) error {
|
||||
if err := downgradePgSQLDatabaseFrom26To25(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradePgSQLDatabaseFromV25(dbHandle)
|
||||
}
|
||||
|
||||
func updatePgSQLDatabaseFrom23To24(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 23 -> 24")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 23 -> 24")
|
||||
|
@ -794,6 +816,17 @@ func updatePgSQLDatabaseFrom24To25(dbHandle *sql.DB) error {
|
|||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 25, true)
|
||||
}
|
||||
|
||||
func updatePgSQLDatabaseFrom25To26(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 25 -> 26")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 25 -> 26")
|
||||
sql := pgsqlV26SQL
|
||||
if config.Driver == CockroachDataProviderName {
|
||||
sql = strings.ReplaceAll(sql, `ALTER TABLE "{{events_rules}}" ALTER COLUMN "status" DROP DEFAULT;`, "")
|
||||
}
|
||||
sql = strings.ReplaceAll(sql, "{{events_rules}}", sqlTableEventsRules)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 26, true)
|
||||
}
|
||||
|
||||
func downgradePgSQLDatabaseFrom24To23(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 24 -> 23")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 24 -> 23")
|
||||
|
@ -810,3 +843,10 @@ func downgradePgSQLDatabaseFrom25To24(dbHandle *sql.DB) error {
|
|||
sql := strings.ReplaceAll(pgsqlV25DownSQL, "{{users}}", sqlTableUsers)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 24, false)
|
||||
}
|
||||
|
||||
func downgradePgSQLDatabaseFrom26To25(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 26 -> 25")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 26 -> 25")
|
||||
sql := strings.ReplaceAll(pgsqlV26DownSQL, "{{events_rules}}", sqlTableEventsRules)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 25, false)
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
sqlDatabaseVersion = 25
|
||||
sqlDatabaseVersion = 26
|
||||
defaultSQLQueryTimeout = 10 * time.Second
|
||||
longSQLQueryTimeout = 60 * time.Second
|
||||
)
|
||||
|
@ -1853,7 +1853,7 @@ func getEventRuleFromDbRow(row sqlScanner) (EventRule, error) {
|
|||
var conditions []byte
|
||||
|
||||
err := row.Scan(&rule.ID, &rule.Name, &description, &rule.CreatedAt, &rule.UpdatedAt, &rule.Trigger,
|
||||
&conditions, &rule.DeletedAt)
|
||||
&conditions, &rule.DeletedAt, &rule.Status)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return rule, util.NewRecordNotFoundError(err.Error())
|
||||
|
@ -3353,7 +3353,7 @@ func sqlCommonAddEventRule(rule *EventRule, dbHandle *sql.DB) error {
|
|||
}
|
||||
q := getAddEventRuleQuery()
|
||||
_, err := tx.ExecContext(ctx, q, rule.Name, rule.Description, util.GetTimeAsMsSinceEpoch(time.Now()),
|
||||
util.GetTimeAsMsSinceEpoch(time.Now()), rule.Trigger, string(conditions))
|
||||
util.GetTimeAsMsSinceEpoch(time.Now()), rule.Trigger, string(conditions), rule.Status)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -3375,7 +3375,7 @@ func sqlCommonUpdateEventRule(rule *EventRule, dbHandle *sql.DB) error {
|
|||
return sqlCommonExecuteTx(ctx, dbHandle, func(tx *sql.Tx) error {
|
||||
q := getUpdateEventRuleQuery()
|
||||
_, err := tx.ExecContext(ctx, q, rule.Description, util.GetTimeAsMsSinceEpoch(time.Now()),
|
||||
rule.Trigger, string(conditions), rule.Name)
|
||||
rule.Trigger, string(conditions), rule.Status, rule.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -177,6 +177,8 @@ DROP TABLE "{{roles}}";
|
|||
`
|
||||
sqliteV25SQL = `ALTER TABLE "{{users}}" ADD COLUMN "last_password_change" bigint DEFAULT 0 NOT NULL;`
|
||||
sqliteV25DownSQL = `ALTER TABLE "{{users}}" DROP COLUMN "last_password_change";`
|
||||
sqliteV26SQL = `ALTER TABLE "{{events_rules}}" ADD COLUMN "status" integer DEFAULT 1 NOT NULL;`
|
||||
sqliteV26DownSQL = `ALTER TABLE "{{events_rules}}" DROP COLUMN "status";`
|
||||
)
|
||||
|
||||
// SQLiteProvider defines the auth provider for SQLite database
|
||||
|
@ -673,6 +675,8 @@ func (p *SQLiteProvider) migrateDatabase() error { //nolint:dupl
|
|||
return updateSQLiteDatabaseFromV23(p.dbHandle)
|
||||
case version == 24:
|
||||
return updateSQLiteDatabaseFromV24(p.dbHandle)
|
||||
case version == 25:
|
||||
return updateSQLiteDatabaseFromV25(p.dbHandle)
|
||||
default:
|
||||
if version > sqlDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
@ -699,6 +703,8 @@ func (p *SQLiteProvider) revertDatabase(targetVersion int) error {
|
|||
return downgradeSQLiteDatabaseFromV24(p.dbHandle)
|
||||
case 25:
|
||||
return downgradeSQLiteDatabaseFromV25(p.dbHandle)
|
||||
case 26:
|
||||
return downgradeSQLiteDatabaseFromV26(p.dbHandle)
|
||||
default:
|
||||
return fmt.Errorf("database schema version not handled: %d", dbVersion.Version)
|
||||
}
|
||||
|
@ -717,7 +723,14 @@ func updateSQLiteDatabaseFromV23(dbHandle *sql.DB) error {
|
|||
}
|
||||
|
||||
func updateSQLiteDatabaseFromV24(dbHandle *sql.DB) error {
|
||||
return updateSQLiteDatabaseFrom24To25(dbHandle)
|
||||
if err := updateSQLiteDatabaseFrom24To25(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updateSQLiteDatabaseFromV25(dbHandle)
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFromV25(dbHandle *sql.DB) error {
|
||||
return updateSQLiteDatabaseFrom25To26(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFromV24(dbHandle *sql.DB) error {
|
||||
|
@ -731,6 +744,13 @@ func downgradeSQLiteDatabaseFromV25(dbHandle *sql.DB) error {
|
|||
return downgradeSQLiteDatabaseFromV24(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFromV26(dbHandle *sql.DB) error {
|
||||
if err := downgradeSQLiteDatabaseFrom26To25(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradeSQLiteDatabaseFromV25(dbHandle)
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFrom23To24(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 23 -> 24")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 23 -> 24")
|
||||
|
@ -748,6 +768,13 @@ func updateSQLiteDatabaseFrom24To25(dbHandle *sql.DB) error {
|
|||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 25, true)
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFrom25To26(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 25 -> 26")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 25 -> 26")
|
||||
sql := strings.ReplaceAll(sqliteV26SQL, "{{events_rules}}", sqlTableEventsRules)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 26, true)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFrom24To23(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 24 -> 23")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 24 -> 23")
|
||||
|
@ -765,6 +792,13 @@ func downgradeSQLiteDatabaseFrom25To24(dbHandle *sql.DB) error {
|
|||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 24, false)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFrom26To25(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 26 -> 25")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 26 -> 25")
|
||||
sql := strings.ReplaceAll(sqliteV26DownSQL, "{{events_rules}}", sqlTableEventsRules)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 25, false)
|
||||
}
|
||||
|
||||
/*func setPragmaFK(dbHandle *sql.DB, value string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
|
||||
defer cancel()
|
||||
|
|
|
@ -61,10 +61,10 @@ func getSQLQuotedName(name string) string {
|
|||
|
||||
func getSelectEventRuleFields() string {
|
||||
if config.Driver == MySQLDataProviderName {
|
||||
return "id,name,description,created_at,updated_at,`trigger`,conditions,deleted_at"
|
||||
return "id,name,description,created_at,updated_at,`trigger`,conditions,deleted_at,status"
|
||||
}
|
||||
|
||||
return `id,name,description,created_at,updated_at,"trigger",conditions,deleted_at`
|
||||
return `id,name,description,created_at,updated_at,"trigger",conditions,deleted_at,status`
|
||||
}
|
||||
|
||||
func getCoalesceDefaultForRole(role string) string {
|
||||
|
@ -973,16 +973,16 @@ func getEventRulesByNameQuery() string {
|
|||
}
|
||||
|
||||
func getAddEventRuleQuery() string {
|
||||
return fmt.Sprintf(`INSERT INTO %s (name,description,created_at,updated_at,%s,conditions,deleted_at)
|
||||
VALUES (%s,%s,%s,%s,%s,%s,0)`,
|
||||
return fmt.Sprintf(`INSERT INTO %s (name,description,created_at,updated_at,%s,conditions,deleted_at,status)
|
||||
VALUES (%s,%s,%s,%s,%s,%s,0,%s)`,
|
||||
sqlTableEventsRules, getSQLQuotedName("trigger"), sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2],
|
||||
sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5])
|
||||
sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6])
|
||||
}
|
||||
|
||||
func getUpdateEventRuleQuery() string {
|
||||
return fmt.Sprintf(`UPDATE %s SET description=%s,updated_at=%s,%s=%s,conditions=%s WHERE name = %s`,
|
||||
return fmt.Sprintf(`UPDATE %s SET description=%s,updated_at=%s,%s=%s,conditions=%s,status=%s WHERE name = %s`,
|
||||
sqlTableEventsRules, sqlPlaceholders[0], sqlPlaceholders[1], getSQLQuotedName("trigger"), sqlPlaceholders[2],
|
||||
sqlPlaceholders[3], sqlPlaceholders[4])
|
||||
sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5])
|
||||
}
|
||||
|
||||
func getDeleteEventRuleQuery(softDelete bool) string {
|
||||
|
|
|
@ -212,7 +212,7 @@ func restoreBackup(content []byte, inputFile string, scanQuota, mode int, execut
|
|||
return err
|
||||
}
|
||||
|
||||
if err = RestoreEventRules(dump.EventRules, inputFile, mode, executor, ipAddress, role); err != nil {
|
||||
if err = RestoreEventRules(dump.EventRules, inputFile, mode, executor, ipAddress, role, dump.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -331,9 +331,14 @@ func RestoreEventActions(actions []dataprovider.BaseEventAction, inputFile strin
|
|||
}
|
||||
|
||||
// RestoreEventRules restores the specified event rules
|
||||
func RestoreEventRules(rules []dataprovider.EventRule, inputFile string, mode int, executor, ipAddress, role string) error {
|
||||
func RestoreEventRules(rules []dataprovider.EventRule, inputFile string, mode int, executor, ipAddress,
|
||||
role string, dumpVersion int,
|
||||
) error {
|
||||
for _, rule := range rules {
|
||||
rule := rule // pin
|
||||
if dumpVersion < 15 {
|
||||
rule.Status = 1
|
||||
}
|
||||
r, err := dataprovider.EventRuleExists(rule.Name)
|
||||
if err == nil {
|
||||
if mode == 1 {
|
||||
|
|
|
@ -1408,6 +1408,7 @@ func TestBasicActionRulesHandling(t *testing.T) {
|
|||
|
||||
r := dataprovider.EventRule{
|
||||
Name: "test rule name",
|
||||
Status: 1,
|
||||
Description: "",
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
|
@ -1629,6 +1630,7 @@ func TestActionRuleRelations(t *testing.T) {
|
|||
Order: 10,
|
||||
},
|
||||
}
|
||||
rule2.Status = 1
|
||||
rule2, _, err = httpdtest.UpdateEventRule(r2, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, rule2.Actions, 1) {
|
||||
|
@ -1936,6 +1938,11 @@ func TestEventRuleValidation(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Contains(t, string(resp), "name is mandatory")
|
||||
rule.Name = "r"
|
||||
rule.Status = 100
|
||||
_, resp, err = httpdtest.AddEventRule(rule, http.StatusBadRequest)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, string(resp), "invalid event rule status")
|
||||
rule.Status = 1
|
||||
rule.Trigger = 1000
|
||||
_, resp, err = httpdtest.AddEventRule(rule, http.StatusBadRequest)
|
||||
assert.NoError(t, err)
|
||||
|
@ -6522,7 +6529,9 @@ func TestProviderErrors(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
user = getTestUser()
|
||||
user.ID = 1
|
||||
backupData := dataprovider.BackupData{}
|
||||
backupData := dataprovider.BackupData{
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupData.Users = append(backupData.Users, user)
|
||||
backupContent, err := json.Marshal(backupData)
|
||||
assert.NoError(t, err)
|
||||
|
@ -6591,6 +6600,7 @@ func TestProviderErrors(t *testing.T) {
|
|||
Type: dataprovider.ActionTypeFolderQuotaReset,
|
||||
},
|
||||
},
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupContent, err = json.Marshal(backupData)
|
||||
assert.NoError(t, err)
|
||||
|
@ -6623,6 +6633,7 @@ func TestProviderErrors(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupContent, err = json.Marshal(backupData)
|
||||
assert.NoError(t, err)
|
||||
|
@ -6636,6 +6647,7 @@ func TestProviderErrors(t *testing.T) {
|
|||
Name: "role1",
|
||||
},
|
||||
},
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupContent, err = json.Marshal(backupData)
|
||||
assert.NoError(t, err)
|
||||
|
@ -7036,7 +7048,9 @@ func TestRestoreShares(t *testing.T) {
|
|||
UsedTokens: 8,
|
||||
AllowFrom: []string{"127.0.0.0/8"},
|
||||
}
|
||||
backupData := dataprovider.BackupData{}
|
||||
backupData := dataprovider.BackupData{
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupData.Shares = append(backupData.Shares, share)
|
||||
backupContent, err := json.Marshal(backupData)
|
||||
assert.NoError(t, err)
|
||||
|
@ -7088,7 +7102,9 @@ func TestLoaddataFromPostBody(t *testing.T) {
|
|||
admin.Permissions = []string{dataprovider.PermAdminAddUsers, dataprovider.PermAdminChangeUsers,
|
||||
dataprovider.PermAdminDeleteUsers, dataprovider.PermAdminViewUsers}
|
||||
admin.Role = role.Name
|
||||
backupData := dataprovider.BackupData{}
|
||||
backupData := dataprovider.BackupData{
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupData.Users = append(backupData.Users, user)
|
||||
backupData.Groups = append(backupData.Groups, group)
|
||||
backupData.Admins = append(backupData.Admins, admin)
|
||||
|
@ -7273,7 +7289,9 @@ func TestLoaddata(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
backupData := dataprovider.BackupData{}
|
||||
backupData := dataprovider.BackupData{
|
||||
Version: 14,
|
||||
}
|
||||
backupData.Users = append(backupData.Users, user)
|
||||
backupData.Roles = append(backupData.Roles, role)
|
||||
backupData.Groups = append(backupData.Groups, group)
|
||||
|
@ -7350,6 +7368,7 @@ func TestLoaddata(t *testing.T) {
|
|||
|
||||
rule, _, err = httpdtest.GetEventRuleByName(rule.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, rule.Status)
|
||||
if assert.Len(t, rule.Actions, 1) {
|
||||
if assert.NotNil(t, rule.Actions[0].BaseEventAction.Options.HTTPConfig.Password) {
|
||||
assert.Equal(t, sdkkms.SecretStatusSecretBox, rule.Actions[0].BaseEventAction.Options.HTTPConfig.Password.GetStatus())
|
||||
|
@ -7516,7 +7535,9 @@ func TestLoaddataMode(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
backupData := dataprovider.BackupData{}
|
||||
backupData := dataprovider.BackupData{
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupData.Users = append(backupData.Users, user)
|
||||
backupData.Groups = append(backupData.Groups, group)
|
||||
backupData.Admins = append(backupData.Admins, admin)
|
||||
|
@ -7603,6 +7624,7 @@ func TestLoaddataMode(t *testing.T) {
|
|||
|
||||
rule, _, err = httpdtest.GetEventRuleByName(rule.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, rule.Status)
|
||||
oldRuleDesc := rule.Description
|
||||
rule.Description = "new rule description"
|
||||
rule, _, err = httpdtest.UpdateEventRule(rule, http.StatusOK)
|
||||
|
@ -17653,7 +17675,9 @@ func TestWebMaintenanceMock(t *testing.T) {
|
|||
Key: fmt.Sprintf("%v.%v", util.GenerateUniqueID(), util.GenerateUniqueID()),
|
||||
Scope: dataprovider.APIKeyScopeAdmin,
|
||||
}
|
||||
backupData := dataprovider.BackupData{}
|
||||
backupData := dataprovider.BackupData{
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupData.Users = append(backupData.Users, user)
|
||||
backupData.Admins = append(backupData.Admins, admin)
|
||||
backupData.APIKeys = append(backupData.APIKeys, apiKey)
|
||||
|
@ -19027,7 +19051,9 @@ func TestFolderTemplateMock(t *testing.T) {
|
|||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, rr)
|
||||
|
||||
dump = dataprovider.BackupData{}
|
||||
dump = dataprovider.BackupData{
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
err = json.Unmarshal(rr.Body.Bytes(), &dump)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, dump.Users, 0)
|
||||
|
@ -20530,6 +20556,7 @@ func TestWebEventRule(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
rule := dataprovider.EventRule{
|
||||
Name: "test_web_rule",
|
||||
Status: 1,
|
||||
Description: "rule added using web API",
|
||||
Trigger: dataprovider.EventTriggerSchedule,
|
||||
Conditions: dataprovider.EventConditions{
|
||||
|
@ -20574,13 +20601,22 @@ func TestWebEventRule(t *testing.T) {
|
|||
form := make(url.Values)
|
||||
form.Set("name", rule.Name)
|
||||
form.Set("description", rule.Description)
|
||||
form.Set("trigger", "a")
|
||||
form.Set("status", "a")
|
||||
req, err := http.NewRequest(http.MethodPost, webAdminEventRulePath, bytes.NewBuffer([]byte(form.Encode())))
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
setJWTCookieForReq(req, webToken)
|
||||
rr := executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, rr)
|
||||
assert.Contains(t, rr.Body.String(), "invalid status")
|
||||
form.Set("status", fmt.Sprintf("%d", rule.Status))
|
||||
form.Set("trigger", "a")
|
||||
req, err = http.NewRequest(http.MethodPost, webAdminEventRulePath, bytes.NewBuffer([]byte(form.Encode())))
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
setJWTCookieForReq(req, webToken)
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, rr)
|
||||
assert.Contains(t, rr.Body.String(), "invalid trigger")
|
||||
form.Set("trigger", fmt.Sprintf("%d", rule.Trigger))
|
||||
form.Set("schedule_hour0", rule.Conditions.Schedules[0].Hours)
|
||||
|
@ -20668,13 +20704,15 @@ func TestWebEventRule(t *testing.T) {
|
|||
ruleGet, _, err := httpdtest.GetEventRuleByName(rule.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, rule.Trigger, ruleGet.Trigger)
|
||||
assert.Equal(t, rule.Status, ruleGet.Status)
|
||||
assert.Equal(t, rule.Description, ruleGet.Description)
|
||||
assert.Equal(t, rule.Conditions, ruleGet.Conditions)
|
||||
if assert.Len(t, ruleGet.Actions, 1) {
|
||||
assert.Equal(t, rule.Actions[0].Name, ruleGet.Actions[0].Name)
|
||||
assert.Equal(t, rule.Actions[0].Order, ruleGet.Actions[0].Order)
|
||||
}
|
||||
// change rule trigger
|
||||
// change rule trigger and status
|
||||
rule.Status = 0
|
||||
rule.Trigger = dataprovider.EventTriggerFsEvent
|
||||
rule.Conditions = dataprovider.EventConditions{
|
||||
FsEvents: []string{"upload", "download"},
|
||||
|
@ -20707,6 +20745,7 @@ func TestWebEventRule(t *testing.T) {
|
|||
MaxFileSize: 5 * 1024 * 1024,
|
||||
},
|
||||
}
|
||||
form.Set("status", fmt.Sprintf("%d", rule.Status))
|
||||
form.Set("trigger", fmt.Sprintf("%d", rule.Trigger))
|
||||
for _, event := range rule.Conditions.FsEvents {
|
||||
form.Add("fs_events", event)
|
||||
|
@ -20727,6 +20766,7 @@ func TestWebEventRule(t *testing.T) {
|
|||
// check the rule
|
||||
ruleGet, _, err = httpdtest.GetEventRuleByName(rule.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, rule.Status, ruleGet.Status)
|
||||
assert.Equal(t, rule.Trigger, ruleGet.Trigger)
|
||||
assert.Equal(t, rule.Description, ruleGet.Description)
|
||||
assert.Equal(t, rule.Conditions, ruleGet.Conditions)
|
||||
|
|
|
@ -2339,6 +2339,10 @@ func getEventRuleFromPostFields(r *http.Request) (dataprovider.EventRule, error)
|
|||
if err != nil {
|
||||
return dataprovider.EventRule{}, err
|
||||
}
|
||||
status, err := strconv.Atoi(r.Form.Get("status"))
|
||||
if err != nil {
|
||||
return dataprovider.EventRule{}, fmt.Errorf("invalid status: %w", err)
|
||||
}
|
||||
trigger, err := strconv.Atoi(r.Form.Get("trigger"))
|
||||
if err != nil {
|
||||
return dataprovider.EventRule{}, fmt.Errorf("invalid trigger: %w", err)
|
||||
|
@ -2353,6 +2357,7 @@ func getEventRuleFromPostFields(r *http.Request) (dataprovider.EventRule, error)
|
|||
}
|
||||
rule := dataprovider.EventRule{
|
||||
Name: r.Form.Get("name"),
|
||||
Status: status,
|
||||
Description: r.Form.Get("description"),
|
||||
Trigger: trigger,
|
||||
Conditions: conditions,
|
||||
|
@ -3499,6 +3504,7 @@ func (s *httpdServer) handleWebGetEventRules(w http.ResponseWriter, r *http.Requ
|
|||
func (s *httpdServer) handleWebAddEventRuleGet(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
rule := dataprovider.EventRule{
|
||||
Status: 1,
|
||||
Trigger: dataprovider.EventTriggerFsEvent,
|
||||
}
|
||||
s.renderEventRulePage(w, r, rule, genericPageModeAdd, "")
|
||||
|
|
|
@ -1601,6 +1601,9 @@ func checkEventRule(expected, actual dataprovider.EventRule) error {
|
|||
if dataprovider.ConvertName(expected.Name) != actual.Name {
|
||||
return errors.New("name mismatch")
|
||||
}
|
||||
if expected.Status != actual.Status {
|
||||
return errors.New("status mismatch")
|
||||
}
|
||||
if expected.Description != actual.Description {
|
||||
return errors.New("description mismatch")
|
||||
}
|
||||
|
|
|
@ -382,7 +382,8 @@ func (s *Service) restoreDump(dump *dataprovider.BackupData) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("unable to restore event actions from file %#v: %v", s.LoadDataFrom, err)
|
||||
}
|
||||
err = httpd.RestoreEventRules(dump.EventRules, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem, "", "")
|
||||
err = httpd.RestoreEventRules(dump.EventRules, s.LoadDataFrom, s.LoadDataMode, dataprovider.ActionExecutorSystem,
|
||||
"", "", dump.Version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to restore event rules from file %#v: %v", s.LoadDataFrom, err)
|
||||
}
|
||||
|
|
|
@ -6748,6 +6748,15 @@ components:
|
|||
name:
|
||||
type: string
|
||||
description: unique name
|
||||
status:
|
||||
type: integer
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description: |
|
||||
status:
|
||||
* `0` disabled
|
||||
* `1` enabled
|
||||
description:
|
||||
type: string
|
||||
description: optional description
|
||||
|
|
|
@ -41,6 +41,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idStatus" class="col-sm-2 col-form-label">Status</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idStatus" name="status">
|
||||
<option value="1" {{if eq .Admin.Status 1 }}selected{{end}}>Active</option>
|
||||
<option value="0" {{if eq .Admin.Status 0 }}selected{{end}}>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idEmail" class="col-sm-2 col-form-label">Email</label>
|
||||
<div class="col-sm-10">
|
||||
|
@ -60,16 +70,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idStatus" class="col-sm-2 col-form-label">Status</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idStatus" name="status">
|
||||
<option value="1" {{if eq .Admin.Status 1 }}selected{{end}}>Active</option>
|
||||
<option value="0" {{if eq .Admin.Status 0 }}selected{{end}}>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idPassword" class="col-sm-2 col-form-label">Password</label>
|
||||
<div class="col-sm-10">
|
||||
|
|
|
@ -41,6 +41,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idStatus" class="col-sm-2 col-form-label">Status</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control selectpicker" id="idStatus" name="status">
|
||||
<option value="1" {{if eq .Rule.Status 1 }}selected{{end}}>Active</option>
|
||||
<option value="0" {{if eq .Rule.Status 0 }}selected{{end}}>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="idDescription" class="col-sm-2 col-form-label">Description</label>
|
||||
<div class="col-sm-10">
|
||||
|
|
|
@ -39,6 +39,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Description</th>
|
||||
<th>Trigger</th>
|
||||
<th>Actions</th>
|
||||
|
@ -48,6 +49,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
{{range .Rules}}
|
||||
<tr>
|
||||
<td>{{.Name}}</td>
|
||||
<td>{{if eq .Status 1 }}Active{{else}}Inactive{{end}}</td>
|
||||
<td>{{.Description}}</td>
|
||||
<td>{{.GetTriggerAsString}}</td>
|
||||
<td>{{.GetActionsAsString}}</td>
|
||||
|
@ -184,11 +186,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
],
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"targets": [0,1],
|
||||
"className": "noVis"
|
||||
},
|
||||
{
|
||||
"targets": [3],
|
||||
"targets": [2],
|
||||
"visible": false
|
||||
},
|
||||
{
|
||||
"targets": [4],
|
||||
"render": $.fn.dataTable.render.ellipsis(100, true)
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Reference in a new issue