eventmanager_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package common
  15. import (
  16. "fmt"
  17. "net/http"
  18. "os"
  19. "path"
  20. "path/filepath"
  21. "testing"
  22. "time"
  23. "github.com/sftpgo/sdk"
  24. sdkkms "github.com/sftpgo/sdk/kms"
  25. "github.com/stretchr/testify/assert"
  26. "github.com/drakkan/sftpgo/v2/internal/dataprovider"
  27. "github.com/drakkan/sftpgo/v2/internal/kms"
  28. "github.com/drakkan/sftpgo/v2/internal/util"
  29. "github.com/drakkan/sftpgo/v2/internal/vfs"
  30. )
  31. func TestEventRuleMatch(t *testing.T) {
  32. conditions := dataprovider.EventConditions{
  33. ProviderEvents: []string{"add", "update"},
  34. Options: dataprovider.ConditionOptions{
  35. Names: []dataprovider.ConditionPattern{
  36. {
  37. Pattern: "user1",
  38. InverseMatch: true,
  39. },
  40. },
  41. },
  42. }
  43. res := eventManager.checkProviderEventMatch(conditions, EventParams{
  44. Name: "user1",
  45. Event: "add",
  46. })
  47. assert.False(t, res)
  48. res = eventManager.checkProviderEventMatch(conditions, EventParams{
  49. Name: "user2",
  50. Event: "update",
  51. })
  52. assert.True(t, res)
  53. res = eventManager.checkProviderEventMatch(conditions, EventParams{
  54. Name: "user2",
  55. Event: "delete",
  56. })
  57. assert.False(t, res)
  58. conditions.Options.ProviderObjects = []string{"api_key"}
  59. res = eventManager.checkProviderEventMatch(conditions, EventParams{
  60. Name: "user2",
  61. Event: "update",
  62. ObjectType: "share",
  63. })
  64. assert.False(t, res)
  65. res = eventManager.checkProviderEventMatch(conditions, EventParams{
  66. Name: "user2",
  67. Event: "update",
  68. ObjectType: "api_key",
  69. })
  70. assert.True(t, res)
  71. // now test fs events
  72. conditions = dataprovider.EventConditions{
  73. FsEvents: []string{operationUpload, operationDownload},
  74. Options: dataprovider.ConditionOptions{
  75. Names: []dataprovider.ConditionPattern{
  76. {
  77. Pattern: "user*",
  78. },
  79. {
  80. Pattern: "tester*",
  81. },
  82. },
  83. FsPaths: []dataprovider.ConditionPattern{
  84. {
  85. Pattern: "*.txt",
  86. },
  87. },
  88. Protocols: []string{ProtocolSFTP},
  89. MinFileSize: 10,
  90. MaxFileSize: 30,
  91. },
  92. }
  93. params := EventParams{
  94. Name: "tester4",
  95. Event: operationDelete,
  96. VirtualPath: "/path.txt",
  97. Protocol: ProtocolSFTP,
  98. ObjectName: "path.txt",
  99. FileSize: 20,
  100. }
  101. res = eventManager.checkFsEventMatch(conditions, params)
  102. assert.False(t, res)
  103. params.Event = operationDownload
  104. res = eventManager.checkFsEventMatch(conditions, params)
  105. assert.True(t, res)
  106. params.Name = "name"
  107. res = eventManager.checkFsEventMatch(conditions, params)
  108. assert.False(t, res)
  109. params.Name = "user5"
  110. res = eventManager.checkFsEventMatch(conditions, params)
  111. assert.True(t, res)
  112. params.VirtualPath = "/sub/f.jpg"
  113. params.ObjectName = path.Base(params.VirtualPath)
  114. res = eventManager.checkFsEventMatch(conditions, params)
  115. assert.False(t, res)
  116. params.VirtualPath = "/sub/f.txt"
  117. params.ObjectName = path.Base(params.VirtualPath)
  118. res = eventManager.checkFsEventMatch(conditions, params)
  119. assert.True(t, res)
  120. params.Protocol = ProtocolHTTP
  121. res = eventManager.checkFsEventMatch(conditions, params)
  122. assert.False(t, res)
  123. params.Protocol = ProtocolSFTP
  124. params.FileSize = 5
  125. res = eventManager.checkFsEventMatch(conditions, params)
  126. assert.False(t, res)
  127. params.FileSize = 50
  128. res = eventManager.checkFsEventMatch(conditions, params)
  129. assert.False(t, res)
  130. params.FileSize = 25
  131. res = eventManager.checkFsEventMatch(conditions, params)
  132. assert.True(t, res)
  133. // bad pattern
  134. conditions.Options.Names = []dataprovider.ConditionPattern{
  135. {
  136. Pattern: "[-]",
  137. },
  138. }
  139. res = eventManager.checkFsEventMatch(conditions, params)
  140. assert.False(t, res)
  141. }
  142. func TestEventManager(t *testing.T) {
  143. startEventScheduler()
  144. action := &dataprovider.BaseEventAction{
  145. Name: "test_action",
  146. Type: dataprovider.ActionTypeHTTP,
  147. Options: dataprovider.BaseEventActionOptions{
  148. HTTPConfig: dataprovider.EventActionHTTPConfig{
  149. Endpoint: "http://localhost",
  150. Timeout: 20,
  151. Method: http.MethodGet,
  152. },
  153. },
  154. }
  155. err := dataprovider.AddEventAction(action, "", "")
  156. assert.NoError(t, err)
  157. rule := &dataprovider.EventRule{
  158. Name: "rule",
  159. Trigger: dataprovider.EventTriggerFsEvent,
  160. Conditions: dataprovider.EventConditions{
  161. FsEvents: []string{operationUpload},
  162. },
  163. Actions: []dataprovider.EventAction{
  164. {
  165. BaseEventAction: dataprovider.BaseEventAction{
  166. Name: action.Name,
  167. },
  168. Order: 1,
  169. },
  170. },
  171. }
  172. err = dataprovider.AddEventRule(rule, "", "")
  173. assert.NoError(t, err)
  174. eventManager.RLock()
  175. assert.Len(t, eventManager.FsEvents, 1)
  176. assert.Len(t, eventManager.ProviderEvents, 0)
  177. assert.Len(t, eventManager.Schedules, 0)
  178. assert.Len(t, eventManager.schedulesMapping, 0)
  179. eventManager.RUnlock()
  180. rule.Trigger = dataprovider.EventTriggerProviderEvent
  181. rule.Conditions = dataprovider.EventConditions{
  182. ProviderEvents: []string{"add"},
  183. }
  184. err = dataprovider.UpdateEventRule(rule, "", "")
  185. assert.NoError(t, err)
  186. eventManager.RLock()
  187. assert.Len(t, eventManager.FsEvents, 0)
  188. assert.Len(t, eventManager.ProviderEvents, 1)
  189. assert.Len(t, eventManager.Schedules, 0)
  190. assert.Len(t, eventManager.schedulesMapping, 0)
  191. eventManager.RUnlock()
  192. rule.Trigger = dataprovider.EventTriggerSchedule
  193. rule.Conditions = dataprovider.EventConditions{
  194. Schedules: []dataprovider.Schedule{
  195. {
  196. Hours: "0",
  197. DayOfWeek: "*",
  198. DayOfMonth: "*",
  199. Month: "*",
  200. },
  201. },
  202. }
  203. rule.DeletedAt = util.GetTimeAsMsSinceEpoch(time.Now().Add(-12 * time.Hour))
  204. eventManager.addUpdateRuleInternal(*rule)
  205. eventManager.RLock()
  206. assert.Len(t, eventManager.FsEvents, 0)
  207. assert.Len(t, eventManager.ProviderEvents, 0)
  208. assert.Len(t, eventManager.Schedules, 0)
  209. assert.Len(t, eventManager.schedulesMapping, 0)
  210. eventManager.RUnlock()
  211. assert.Eventually(t, func() bool {
  212. _, err = dataprovider.EventRuleExists(rule.Name)
  213. _, ok := err.(*util.RecordNotFoundError)
  214. return ok
  215. }, 2*time.Second, 100*time.Millisecond)
  216. rule.DeletedAt = 0
  217. err = dataprovider.AddEventRule(rule, "", "")
  218. assert.NoError(t, err)
  219. eventManager.RLock()
  220. assert.Len(t, eventManager.FsEvents, 0)
  221. assert.Len(t, eventManager.ProviderEvents, 0)
  222. assert.Len(t, eventManager.Schedules, 1)
  223. assert.Len(t, eventManager.schedulesMapping, 1)
  224. eventManager.RUnlock()
  225. err = dataprovider.DeleteEventRule(rule.Name, "", "")
  226. assert.NoError(t, err)
  227. eventManager.RLock()
  228. assert.Len(t, eventManager.FsEvents, 0)
  229. assert.Len(t, eventManager.ProviderEvents, 0)
  230. assert.Len(t, eventManager.Schedules, 0)
  231. assert.Len(t, eventManager.schedulesMapping, 0)
  232. eventManager.RUnlock()
  233. err = dataprovider.DeleteEventAction(action.Name, "", "")
  234. assert.NoError(t, err)
  235. stopEventScheduler()
  236. }
  237. func TestEventManagerErrors(t *testing.T) {
  238. startEventScheduler()
  239. providerConf := dataprovider.GetProviderConfig()
  240. err := dataprovider.Close()
  241. assert.NoError(t, err)
  242. err = executeUsersQuotaResetRuleAction(dataprovider.ConditionOptions{})
  243. assert.Error(t, err)
  244. err = executeFoldersQuotaResetRuleAction(dataprovider.ConditionOptions{})
  245. assert.Error(t, err)
  246. err = executeTransferQuotaResetRuleAction(dataprovider.ConditionOptions{})
  247. assert.Error(t, err)
  248. eventManager.loadRules()
  249. eventManager.RLock()
  250. assert.Len(t, eventManager.FsEvents, 0)
  251. assert.Len(t, eventManager.ProviderEvents, 0)
  252. assert.Len(t, eventManager.Schedules, 0)
  253. eventManager.RUnlock()
  254. // rule with invalid trigger
  255. eventManager.addUpdateRuleInternal(dataprovider.EventRule{
  256. Name: "test rule",
  257. Trigger: -1,
  258. })
  259. eventManager.RLock()
  260. assert.Len(t, eventManager.FsEvents, 0)
  261. assert.Len(t, eventManager.ProviderEvents, 0)
  262. assert.Len(t, eventManager.Schedules, 0)
  263. eventManager.RUnlock()
  264. // rule with invalid cronspec
  265. eventManager.addUpdateRuleInternal(dataprovider.EventRule{
  266. Name: "test rule",
  267. Trigger: dataprovider.EventTriggerSchedule,
  268. Conditions: dataprovider.EventConditions{
  269. Schedules: []dataprovider.Schedule{
  270. {
  271. Hours: "1000",
  272. },
  273. },
  274. },
  275. })
  276. eventManager.RLock()
  277. assert.Len(t, eventManager.FsEvents, 0)
  278. assert.Len(t, eventManager.ProviderEvents, 0)
  279. assert.Len(t, eventManager.Schedules, 0)
  280. eventManager.RUnlock()
  281. err = dataprovider.Initialize(providerConf, configDir, true)
  282. assert.NoError(t, err)
  283. stopEventScheduler()
  284. }
  285. func TestEventRuleActions(t *testing.T) {
  286. actionName := "test rule action"
  287. action := dataprovider.BaseEventAction{
  288. Name: actionName,
  289. Type: dataprovider.ActionTypeBackup,
  290. }
  291. err := executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{})
  292. assert.NoError(t, err)
  293. action.Type = -1
  294. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{})
  295. assert.Error(t, err)
  296. action = dataprovider.BaseEventAction{
  297. Name: actionName,
  298. Type: dataprovider.ActionTypeHTTP,
  299. Options: dataprovider.BaseEventActionOptions{
  300. HTTPConfig: dataprovider.EventActionHTTPConfig{
  301. Endpoint: "http://foo\x7f.com/", // invalid URL
  302. SkipTLSVerify: true,
  303. Body: "{{ObjectData}}",
  304. Method: http.MethodPost,
  305. QueryParameters: []dataprovider.KeyValue{
  306. {
  307. Key: "param",
  308. Value: "value",
  309. },
  310. },
  311. Timeout: 5,
  312. Headers: []dataprovider.KeyValue{
  313. {
  314. Key: "Content-Type",
  315. Value: "application/json",
  316. },
  317. },
  318. Username: "httpuser",
  319. },
  320. },
  321. }
  322. action.Options.SetEmptySecretsIfNil()
  323. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{})
  324. if assert.Error(t, err) {
  325. assert.Contains(t, err.Error(), "invalid endpoint")
  326. }
  327. action.Options.HTTPConfig.Endpoint = fmt.Sprintf("http://%v", httpAddr)
  328. params := EventParams{
  329. Name: "a",
  330. Object: &dataprovider.User{
  331. BaseUser: sdk.BaseUser{
  332. Username: "test user",
  333. },
  334. },
  335. }
  336. err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
  337. assert.NoError(t, err)
  338. action.Options.HTTPConfig.Endpoint = fmt.Sprintf("http://%v/404", httpAddr)
  339. err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
  340. if assert.Error(t, err) {
  341. assert.Equal(t, err.Error(), "unexpected status code: 404")
  342. }
  343. action.Options.HTTPConfig.Endpoint = "http://invalid:1234"
  344. err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
  345. assert.Error(t, err)
  346. action.Options.HTTPConfig.QueryParameters = nil
  347. action.Options.HTTPConfig.Endpoint = "http://bar\x7f.com/"
  348. err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
  349. assert.Error(t, err)
  350. action.Options.HTTPConfig.Password = kms.NewSecret(sdkkms.SecretStatusSecretBox, "payload", "key", "data")
  351. err = executeRuleAction(action, params, dataprovider.ConditionOptions{})
  352. if assert.Error(t, err) {
  353. assert.Contains(t, err.Error(), "unable to decrypt password")
  354. }
  355. // test disk and transfer quota reset
  356. username1 := "user1"
  357. username2 := "user2"
  358. user1 := dataprovider.User{
  359. BaseUser: sdk.BaseUser{
  360. Username: username1,
  361. HomeDir: filepath.Join(os.TempDir(), username1),
  362. Status: 1,
  363. Permissions: map[string][]string{
  364. "/": {dataprovider.PermAny},
  365. },
  366. },
  367. }
  368. user2 := dataprovider.User{
  369. BaseUser: sdk.BaseUser{
  370. Username: username2,
  371. HomeDir: filepath.Join(os.TempDir(), username2),
  372. Status: 1,
  373. Permissions: map[string][]string{
  374. "/": {dataprovider.PermAny},
  375. },
  376. },
  377. }
  378. err = dataprovider.AddUser(&user1, "", "")
  379. assert.NoError(t, err)
  380. err = dataprovider.AddUser(&user2, "", "")
  381. assert.NoError(t, err)
  382. action = dataprovider.BaseEventAction{
  383. Type: dataprovider.ActionTypeUserQuotaReset,
  384. }
  385. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
  386. Names: []dataprovider.ConditionPattern{
  387. {
  388. Pattern: username1,
  389. },
  390. },
  391. })
  392. assert.Error(t, err) // no home dir
  393. // create the home dir
  394. err = os.MkdirAll(user1.GetHomeDir(), os.ModePerm)
  395. assert.NoError(t, err)
  396. err = os.WriteFile(filepath.Join(user1.GetHomeDir(), "file.txt"), []byte("user"), 0666)
  397. assert.NoError(t, err)
  398. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
  399. Names: []dataprovider.ConditionPattern{
  400. {
  401. Pattern: username1,
  402. },
  403. },
  404. })
  405. assert.NoError(t, err)
  406. userGet, err := dataprovider.UserExists(username1)
  407. assert.NoError(t, err)
  408. assert.Equal(t, 1, userGet.UsedQuotaFiles)
  409. assert.Equal(t, int64(4), userGet.UsedQuotaSize)
  410. // simulate another quota scan in progress
  411. assert.True(t, QuotaScans.AddUserQuotaScan(username1))
  412. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
  413. Names: []dataprovider.ConditionPattern{
  414. {
  415. Pattern: username1,
  416. },
  417. },
  418. })
  419. assert.Error(t, err)
  420. assert.True(t, QuotaScans.RemoveUserQuotaScan(username1))
  421. err = os.RemoveAll(user1.GetHomeDir())
  422. assert.NoError(t, err)
  423. err = dataprovider.UpdateUserTransferQuota(&user1, 100, 100, true)
  424. assert.NoError(t, err)
  425. action.Type = dataprovider.ActionTypeTransferQuotaReset
  426. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
  427. Names: []dataprovider.ConditionPattern{
  428. {
  429. Pattern: username1,
  430. },
  431. },
  432. })
  433. assert.NoError(t, err)
  434. userGet, err = dataprovider.UserExists(username1)
  435. assert.NoError(t, err)
  436. assert.Equal(t, int64(0), userGet.UsedDownloadDataTransfer)
  437. assert.Equal(t, int64(0), userGet.UsedUploadDataTransfer)
  438. err = dataprovider.DeleteUser(username1, "", "")
  439. assert.NoError(t, err)
  440. err = dataprovider.DeleteUser(username2, "", "")
  441. assert.NoError(t, err)
  442. // test folder quota reset
  443. foldername1 := "f1"
  444. foldername2 := "f2"
  445. folder1 := vfs.BaseVirtualFolder{
  446. Name: foldername1,
  447. MappedPath: filepath.Join(os.TempDir(), foldername1),
  448. }
  449. folder2 := vfs.BaseVirtualFolder{
  450. Name: foldername2,
  451. MappedPath: filepath.Join(os.TempDir(), foldername2),
  452. }
  453. err = dataprovider.AddFolder(&folder1, "", "")
  454. assert.NoError(t, err)
  455. err = dataprovider.AddFolder(&folder2, "", "")
  456. assert.NoError(t, err)
  457. action = dataprovider.BaseEventAction{
  458. Type: dataprovider.ActionTypeFolderQuotaReset,
  459. }
  460. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
  461. Names: []dataprovider.ConditionPattern{
  462. {
  463. Pattern: foldername1,
  464. },
  465. },
  466. })
  467. assert.Error(t, err) // no home dir
  468. err = os.MkdirAll(folder1.MappedPath, os.ModePerm)
  469. assert.NoError(t, err)
  470. err = os.WriteFile(filepath.Join(folder1.MappedPath, "file.txt"), []byte("folder"), 0666)
  471. assert.NoError(t, err)
  472. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
  473. Names: []dataprovider.ConditionPattern{
  474. {
  475. Pattern: foldername1,
  476. },
  477. },
  478. })
  479. assert.NoError(t, err)
  480. folderGet, err := dataprovider.GetFolderByName(foldername1)
  481. assert.NoError(t, err)
  482. assert.Equal(t, 1, folderGet.UsedQuotaFiles)
  483. assert.Equal(t, int64(6), folderGet.UsedQuotaSize)
  484. // simulate another quota scan in progress
  485. assert.True(t, QuotaScans.AddVFolderQuotaScan(foldername1))
  486. err = executeRuleAction(action, EventParams{}, dataprovider.ConditionOptions{
  487. Names: []dataprovider.ConditionPattern{
  488. {
  489. Pattern: foldername1,
  490. },
  491. },
  492. })
  493. assert.Error(t, err)
  494. assert.True(t, QuotaScans.RemoveVFolderQuotaScan(foldername1))
  495. err = os.RemoveAll(folder1.MappedPath)
  496. assert.NoError(t, err)
  497. err = dataprovider.DeleteFolder(foldername1, "", "")
  498. assert.NoError(t, err)
  499. err = dataprovider.DeleteFolder(foldername2, "", "")
  500. assert.NoError(t, err)
  501. }
  502. func TestQuotaActionsWithQuotaTrackDisabled(t *testing.T) {
  503. oldProviderConf := dataprovider.GetProviderConfig()
  504. providerConf := dataprovider.GetProviderConfig()
  505. providerConf.TrackQuota = 0
  506. err := dataprovider.Close()
  507. assert.NoError(t, err)
  508. err = dataprovider.Initialize(providerConf, configDir, true)
  509. assert.NoError(t, err)
  510. username := "u1"
  511. user := dataprovider.User{
  512. BaseUser: sdk.BaseUser{
  513. Username: username,
  514. HomeDir: filepath.Join(os.TempDir(), username),
  515. Status: 1,
  516. Permissions: map[string][]string{
  517. "/": {dataprovider.PermAny},
  518. },
  519. },
  520. FsConfig: vfs.Filesystem{
  521. Provider: sdk.LocalFilesystemProvider,
  522. },
  523. }
  524. err = dataprovider.AddUser(&user, "", "")
  525. assert.NoError(t, err)
  526. err = os.MkdirAll(user.GetHomeDir(), os.ModePerm)
  527. assert.NoError(t, err)
  528. err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeUserQuotaReset},
  529. EventParams{}, dataprovider.ConditionOptions{
  530. Names: []dataprovider.ConditionPattern{
  531. {
  532. Pattern: username,
  533. },
  534. },
  535. })
  536. assert.Error(t, err)
  537. err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeTransferQuotaReset},
  538. EventParams{}, dataprovider.ConditionOptions{
  539. Names: []dataprovider.ConditionPattern{
  540. {
  541. Pattern: username,
  542. },
  543. },
  544. })
  545. assert.Error(t, err)
  546. err = os.RemoveAll(user.GetHomeDir())
  547. assert.NoError(t, err)
  548. err = dataprovider.DeleteUser(username, "", "")
  549. assert.NoError(t, err)
  550. foldername := "f1"
  551. folder := vfs.BaseVirtualFolder{
  552. Name: foldername,
  553. MappedPath: filepath.Join(os.TempDir(), foldername),
  554. }
  555. err = dataprovider.AddFolder(&folder, "", "")
  556. assert.NoError(t, err)
  557. err = os.MkdirAll(folder.MappedPath, os.ModePerm)
  558. assert.NoError(t, err)
  559. err = executeRuleAction(dataprovider.BaseEventAction{Type: dataprovider.ActionTypeFolderQuotaReset},
  560. EventParams{}, dataprovider.ConditionOptions{
  561. Names: []dataprovider.ConditionPattern{
  562. {
  563. Pattern: foldername,
  564. },
  565. },
  566. })
  567. assert.Error(t, err)
  568. err = os.RemoveAll(folder.MappedPath)
  569. assert.NoError(t, err)
  570. err = dataprovider.DeleteFolder(foldername, "", "")
  571. assert.NoError(t, err)
  572. err = dataprovider.Close()
  573. assert.NoError(t, err)
  574. err = dataprovider.Initialize(oldProviderConf, configDir, true)
  575. assert.NoError(t, err)
  576. }
  577. func TestScheduledActions(t *testing.T) {
  578. startEventScheduler()
  579. backupsPath := filepath.Join(os.TempDir(), "backups")
  580. err := os.RemoveAll(backupsPath)
  581. assert.NoError(t, err)
  582. action := &dataprovider.BaseEventAction{
  583. Name: "action",
  584. Type: dataprovider.ActionTypeBackup,
  585. }
  586. err = dataprovider.AddEventAction(action, "", "")
  587. assert.NoError(t, err)
  588. rule := &dataprovider.EventRule{
  589. Name: "rule",
  590. Trigger: dataprovider.EventTriggerSchedule,
  591. Conditions: dataprovider.EventConditions{
  592. Schedules: []dataprovider.Schedule{
  593. {
  594. Hours: "11",
  595. DayOfWeek: "*",
  596. DayOfMonth: "*",
  597. Month: "*",
  598. },
  599. },
  600. },
  601. Actions: []dataprovider.EventAction{
  602. {
  603. BaseEventAction: dataprovider.BaseEventAction{
  604. Name: action.Name,
  605. },
  606. Order: 1,
  607. },
  608. },
  609. }
  610. job := eventCronJob{
  611. ruleName: rule.Name,
  612. }
  613. job.Run() // rule not found
  614. assert.NoDirExists(t, backupsPath)
  615. err = dataprovider.AddEventRule(rule, "", "")
  616. assert.NoError(t, err)
  617. job.Run()
  618. assert.DirExists(t, backupsPath)
  619. err = dataprovider.DeleteEventRule(rule.Name, "", "")
  620. assert.NoError(t, err)
  621. err = dataprovider.DeleteEventAction(action.Name, "", "")
  622. assert.NoError(t, err)
  623. err = os.RemoveAll(backupsPath)
  624. assert.NoError(t, err)
  625. stopEventScheduler()
  626. }