diff --git a/mattermost-plugin/Makefile b/mattermost-plugin/Makefile index 152af9121..48bf49f8a 100644 --- a/mattermost-plugin/Makefile +++ b/mattermost-plugin/Makefile @@ -214,7 +214,6 @@ detach: setup-attach ## Runs any lints and unit tests defined for the server and webapp, if they exist. .PHONY: test -test: export FB_UNIT_TESTING=1 test: webapp/node_modules ifneq ($(HAS_SERVER),) $(GO) test -v $(GO_TEST_FLAGS) ./server/... diff --git a/mattermost-plugin/go.mod b/mattermost-plugin/go.mod index 12b112984..32f050002 100644 --- a/mattermost-plugin/go.mod +++ b/mattermost-plugin/go.mod @@ -3,10 +3,8 @@ module github.com/mattermost/focalboard/mattermost-plugin go 1.16 replace github.com/mattermost/focalboard/server => ../server -replace github.com/mattermost/focalboard/server/server => ../server/server require ( - github.com/golang/mock v1.6.0 github.com/mattermost/focalboard/server v0.0.0-20220325164658-33557093b00d github.com/mattermost/mattermost-plugin-api v0.0.27 github.com/mattermost/mattermost-server/v6 v6.5.0 diff --git a/mattermost-plugin/server/configuration.go b/mattermost-plugin/server/configuration.go index 516b512d0..993f5147f 100644 --- a/mattermost-plugin/server/configuration.go +++ b/mattermost-plugin/server/configuration.go @@ -88,11 +88,6 @@ func (p *Plugin) OnConfigurationChange() error { //nolint // handle feature flags p.server.Config().FeatureFlags = parseFeatureFlags(mmconfig.FeatureFlags.ToMap()) - - // handle Data Retention settings - p.server.Config().EnableDataRetention = *mmconfig.DataRetentionSettings.EnableBoardsDeletion - p.server.Config().DataRetentionDays = *mmconfig.DataRetentionSettings.BoardsRetentionDays - p.server.UpdateAppConfig() p.wsPluginAdapter.BroadcastConfigChange(*p.server.App().GetClientConfig()) return nil diff --git a/mattermost-plugin/server/configuration_test.go b/mattermost-plugin/server/configuration_test.go index d7d1a3974..04b19abaf 100644 --- a/mattermost-plugin/server/configuration_test.go +++ b/mattermost-plugin/server/configuration_test.go @@ -1,12 +1,11 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - package main import ( "testing" "github.com/mattermost/focalboard/server/model" + "github.com/mattermost/focalboard/server/server" + "github.com/mattermost/focalboard/server/services/config" "github.com/mattermost/focalboard/server/ws" serverModel "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/plugin/plugintest" @@ -14,6 +13,27 @@ import ( "github.com/stretchr/testify/assert" ) +type TestHelper struct { + Server *server.Server +} + +func SetupTestHelper() *TestHelper { + th := &TestHelper{} + th.Server = newTestServer() + return th +} + +func newTestServer() *server.Server { + srv, err := server.New(server.Params{ + Cfg: &config.Configuration{}, + }) + if err != nil { + panic(err) + } + + return srv +} + func TestConfigurationNullConfiguration(t *testing.T) { plugin := &Plugin{} assert.NotNil(t, plugin.getConfiguration()) @@ -33,24 +53,16 @@ func TestOnConfigurationChange(t *testing.T) { Directory: &stringRef, Plugins: basePlugins, } - falseRef := false - intRef := 365 - baseDataRetentionSettings := &serverModel.DataRetentionSettings{ - EnableBoardsDeletion: &falseRef, - BoardsRetentionDays: &intRef, - } baseConfig := &serverModel.Config{ - FeatureFlags: baseFeatureFlags, - PluginSettings: *basePluginSettings, - DataRetentionSettings: *baseDataRetentionSettings, + FeatureFlags: baseFeatureFlags, + PluginSettings: *basePluginSettings, } t.Run("Test Load Plugin Success", func(t *testing.T) { - th := SetupTestHelper(t) + th := SetupTestHelper() api := &plugintest.API{} api.On("GetUnsanitizedConfig").Return(baseConfig) - api.On("GetConfig").Return(baseConfig) p := Plugin{} p.SetAPI(api) diff --git a/mattermost-plugin/server/helpers_test.go b/mattermost-plugin/server/helpers_test.go deleted file mode 100644 index 932e2e302..000000000 --- a/mattermost-plugin/server/helpers_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package main - -import ( - "testing" - - "github.com/golang/mock/gomock" - "github.com/mattermost/focalboard/server/server" - "github.com/mattermost/focalboard/server/services/config" - "github.com/mattermost/focalboard/server/services/permissions/localpermissions" - "github.com/mattermost/focalboard/server/services/store/mockstore" - "github.com/mattermost/mattermost-server/v6/shared/mlog" -) - -type TestHelper struct { - Server *server.Server - Store *mockstore.MockStore -} - -func SetupTestHelper(t *testing.T) *TestHelper { - th := &TestHelper{} - - ctrl := gomock.NewController(t) - defer ctrl.Finish() - mockStore := mockstore.NewMockStore(ctrl) - - th.Server = newTestServer(t, mockStore) - th.Store = mockStore - - return th -} - -func newTestServer(t *testing.T, mockStore *mockstore.MockStore) *server.Server { - config := &config.Configuration{ - EnableDataRetention: false, - DataRetentionDays: 10, - FilesDriver: "local", - FilesPath: "./files", - WebPath: "/", - } - - logger, err := mlog.NewLogger() - if err = logger.Configure("", config.LoggingCfgJSON, nil); err != nil { - panic(err) - } - - mockStore.EXPECT().GetTeam(gomock.Any()).Return(nil, nil).AnyTimes() - mockStore.EXPECT().UpsertTeamSignupToken(gomock.Any()).AnyTimes() - mockStore.EXPECT().GetSystemSettings().AnyTimes() - mockStore.EXPECT().SetSystemSetting(gomock.Any(), gomock.Any()).AnyTimes() - - permissionsService := localpermissions.New(mockStore, logger) - - srv, err := server.New(server.Params{ - Cfg: config, - DBStore: mockStore, - Logger: logger, - PermissionsService: permissionsService, - SkipTemplateInit: true, - }) - if err != nil { - panic(err) - } - - return srv -} diff --git a/mattermost-plugin/server/plugin.go b/mattermost-plugin/server/plugin.go index 72128db45..21c47b3f0 100644 --- a/mattermost-plugin/server/plugin.go +++ b/mattermost-plugin/server/plugin.go @@ -2,7 +2,6 @@ package main import ( "encoding/json" - "errors" "fmt" "math" "net/http" @@ -10,7 +9,6 @@ import ( "path" "strings" "sync" - "time" "github.com/mattermost/focalboard/server/auth" "github.com/mattermost/focalboard/server/server" @@ -40,8 +38,6 @@ const ( notifyFreqBoardSecondsKey = "notify_freq_board_seconds" ) -var ErrInsufficientLicense = errors.New("appropriate license required") - type BoardsEmbed struct { OriginalPath string `json:"originalPath"` TeamID string `json:"teamID"` @@ -240,8 +236,6 @@ func (p *Plugin) createBoardsConfig(mmconfig mmModel.Config, baseURL string, ser FeatureFlags: featureFlags, NotifyFreqCardSeconds: getPluginSettingInt(mmconfig, notifyFreqCardSecondsKey, 120), NotifyFreqBoardSeconds: getPluginSettingInt(mmconfig, notifyFreqBoardSecondsKey, 86400), - EnableDataRetention: *mmconfig.DataRetentionSettings.EnableBoardsDeletion, - DataRetentionDays: *mmconfig.DataRetentionSettings.BoardsRetentionDays, } } @@ -508,24 +502,3 @@ func isBoardsLink(link string) bool { teamID, boardID, viewID, cardID := returnBoardsParams(pathSplit) return teamID != "" && boardID != "" && viewID != "" && cardID != "" } - -func (p *Plugin) RunDataRetention(nowTime, batchSize int64) (int64, error) { - p.server.Logger().Debug("Boards RunDataRetention") - license := p.server.Store().GetLicense() - if license == nil || !(*license.Features.DataRetention) { - return 0, ErrInsufficientLicense - } - - if p.server.Config().EnableDataRetention { - boardsRetentionDays := p.server.Config().DataRetentionDays - endTimeBoards := convertDaysToCutoff(boardsRetentionDays, time.Unix(nowTime/1000, 0)) - return p.server.Store().RunDataRetention(endTimeBoards, batchSize) - } - return 0, nil -} - -func convertDaysToCutoff(days int, now time.Time) int64 { - upToStartOfDay := now.AddDate(0, 0, -days) - cutoffDate := time.Date(upToStartOfDay.Year(), upToStartOfDay.Month(), upToStartOfDay.Day(), 0, 0, 0, 0, time.Local) - return cutoffDate.UnixNano() / int64(time.Millisecond) -} diff --git a/mattermost-plugin/server/plugin_test.go b/mattermost-plugin/server/plugin_test.go index 9e30ea123..d8c79522b 100644 --- a/mattermost-plugin/server/plugin_test.go +++ b/mattermost-plugin/server/plugin_test.go @@ -1,44 +1,21 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - package main import ( - "io" "io/ioutil" "net/http" "net/http/httptest" "testing" - "time" - "github.com/golang/mock/gomock" "github.com/mattermost/mattermost-server/v6/model" "github.com/stretchr/testify/assert" ) -func testHandler(w http.ResponseWriter, r *http.Request) { - // A very simple health check. - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - - // In the future we could report back on the status of our DB, or our cache - // (e.g. Redis) by performing a simple PING, and include them in the response. - io.WriteString(w, "Hello, world!") -} - func TestServeHTTP(t *testing.T) { assert := assert.New(t) - th := SetupTestHelper(t) plugin := Plugin{} - - testHandler := http.HandlerFunc(testHandler) - th.Server.GetRootRouter().Handle("/", testHandler) - - plugin.server = th.Server w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodGet, "/", nil) - // plugin.server. plugin.ServeHTTP(nil, w, r) result := w.Result() @@ -54,7 +31,6 @@ func TestServeHTTP(t *testing.T) { func TestSetConfiguration(t *testing.T) { plugin := Plugin{} boolTrue := true - boolFalse := false stringRef := "" baseFeatureFlags := &model.FeatureFlags{} @@ -69,25 +45,16 @@ func TestSetConfiguration(t *testing.T) { } directory := "testDirectory" - maxFileSize := int64(1048576000) baseFileSettings := &model.FileSettings{ - DriverName: &driverName, - Directory: &directory, - MaxFileSize: &maxFileSize, - } - - days := 365 - baseDataRetentionSettings := &model.DataRetentionSettings{ - EnableBoardsDeletion: &boolFalse, - BoardsRetentionDays: &days, + DriverName: &driverName, + Directory: &directory, } baseConfig := &model.Config{ - FeatureFlags: baseFeatureFlags, - PluginSettings: *basePluginSettings, - SqlSettings: *baseSQLSettings, - FileSettings: *baseFileSettings, - DataRetentionSettings: *baseDataRetentionSettings, + FeatureFlags: baseFeatureFlags, + PluginSettings: *basePluginSettings, + SqlSettings: *baseSQLSettings, + FileSettings: *baseFileSettings, } t.Run("test enable telemetry", func(t *testing.T) { @@ -129,65 +96,3 @@ func TestSetConfiguration(t *testing.T) { assert.Equal(t, "true", config.FeatureFlags["myTest"]) }) } - -func TestRunDataRetention(t *testing.T) { - th := SetupTestHelper(t) - plugin := Plugin{} - plugin.server = th.Server - - now := time.Now().UnixNano() - - t.Run("test null license", func(t *testing.T) { - th.Store.EXPECT().GetLicense().Return(nil) - _, err := plugin.RunDataRetention(now, 10) - assert.NotNil(t, err) - assert.Equal(t, ErrInsufficientLicense, err) - }) - - t.Run("test invalid license", func(t *testing.T) { - falseValue := false - - th.Store.EXPECT().GetLicense().Return( - &model.License{ - Features: &model.Features{ - DataRetention: &falseValue, - }, - }, - ) - _, err := plugin.RunDataRetention(now, 10) - assert.NotNil(t, err) - assert.Equal(t, ErrInsufficientLicense, err) - }) - - t.Run("test valid license, invalid config", func(t *testing.T) { - trueValue := true - th.Store.EXPECT().GetLicense().Return( - &model.License{ - Features: &model.Features{ - DataRetention: &trueValue, - }, - }) - - count, err := plugin.RunDataRetention(now, 10) - assert.Nil(t, err) - assert.Equal(t, int64(0), count) - }) - - t.Run("test valid license, valid config", func(t *testing.T) { - trueValue := true - th.Store.EXPECT().GetLicense().Return( - &model.License{ - Features: &model.Features{ - DataRetention: &trueValue, - }, - }) - - th.Store.EXPECT().RunDataRetention(gomock.Any(), int64(10)).Return(int64(100), nil) - plugin.server.Config().EnableDataRetention = true - - count, err := plugin.RunDataRetention(now, 10) - - assert.Nil(t, err) - assert.Equal(t, int64(100), count) - }) -} diff --git a/server/server/params.go b/server/server/params.go index 01ceb8bb9..553d30c03 100644 --- a/server/server/params.go +++ b/server/server/params.go @@ -21,7 +21,6 @@ type Params struct { WSAdapter ws.Adapter NotifyBackends []notify.Backend PermissionsService permissions.PermissionsService - SkipTemplateInit bool } func (p Params) CheckValid() error { diff --git a/server/server/server.go b/server/server/server.go index ade5129ff..cd5d7ab1e 100644 --- a/server/server/server.go +++ b/server/server/server.go @@ -357,10 +357,6 @@ func (s *Server) App() *app.App { return s.app } -func (s *Server) Store() store.Store { - return s.store -} - func (s *Server) UpdateAppConfig() { s.app.SetConfig(s.config) } diff --git a/server/services/config/config.go b/server/services/config/config.go index f64fcc4d8..43b41c74f 100644 --- a/server/services/config/config.go +++ b/server/services/config/config.go @@ -50,8 +50,6 @@ type Configuration struct { LocalModeSocketLocation string `json:"localModeSocketLocation" mapstructure:"localModeSocketLocation"` EnablePublicSharedBoards bool `json:"enablePublicSharedBoards" mapstructure:"enablePublicSharedBoards"` FeatureFlags map[string]string `json:"featureFlags" mapstructure:"featureFlags"` - EnableDataRetention bool `json:"enable_data_retention" mapstructure:"enable_data_retention"` - DataRetentionDays int `json:"data_retention_days" mapstructure:"data_retention_days"` AuthMode string `json:"authMode" mapstructure:"authMode"` @@ -97,8 +95,6 @@ func ReadConfigFile(configFilePath string) (*Configuration, error) { viper.SetDefault("AuthMode", "native") viper.SetDefault("NotifyFreqCardSeconds", 120) // 2 minutes after last card edit viper.SetDefault("NotifyFreqBoardSeconds", 86400) // 1 day after last card edit - viper.SetDefault("EnableDataRetention", false) - viper.SetDefault("DataRetentionDays", 365) // 1 year is default viper.SetDefault("PrometheusAddress", "") err := viper.ReadInConfig() // Find and read the config file diff --git a/server/services/store/mockstore/mockstore.go b/server/services/store/mockstore/mockstore.go index a9417810b..2046ddec1 100644 --- a/server/services/store/mockstore/mockstore.go +++ b/server/services/store/mockstore/mockstore.go @@ -1128,21 +1128,6 @@ func (mr *MockStoreMockRecorder) RemoveDefaultTemplates(arg0 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveDefaultTemplates", reflect.TypeOf((*MockStore)(nil).RemoveDefaultTemplates), arg0) } -// RunDataRetention mocks base method. -func (m *MockStore) RunDataRetention(arg0, arg1 int64) (int64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RunDataRetention", arg0, arg1) - ret0, _ := ret[0].(int64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RunDataRetention indicates an expected call of RunDataRetention. -func (mr *MockStoreMockRecorder) RunDataRetention(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunDataRetention", reflect.TypeOf((*MockStore)(nil).RunDataRetention), arg0, arg1) -} - // SaveMember mocks base method. func (m *MockStore) SaveMember(arg0 *model.BoardMember) (*model.BoardMember, error) { m.ctrl.T.Helper() diff --git a/server/services/store/sqlstore/blocks.go b/server/services/store/sqlstore/blocks.go index fb2958cab..a79ddfda0 100644 --- a/server/services/store/sqlstore/blocks.go +++ b/server/services/store/sqlstore/blocks.go @@ -4,13 +4,9 @@ import ( "database/sql" "encoding/json" "fmt" - "strconv" - "strings" - "time" "github.com/mattermost/focalboard/server/services/store" "github.com/mattermost/focalboard/server/utils" - "github.com/pkg/errors" sq "github.com/Masterminds/squirrel" _ "github.com/lib/pq" // postgres driver @@ -748,113 +744,6 @@ func (s *SQLStore) replaceBlockID(db sq.BaseRunner, currentID, newID, workspaceI return nil } -func (s *SQLStore) runDataRetention(db sq.BaseRunner, globalRetentionDate int64, batchSize int64) (int64, error) { - mlog.Info("Start Boards Data Retention", - mlog.String("Global Retention Date", time.Unix(globalRetentionDate/1000, 0).String()), - mlog.Int64("Raw Date", globalRetentionDate)) - deleteTables := map[string]string{ - "blocks": "board_id", - "blocks_history": "board_id", - "boards": "id", - "boards_history": "id", - "board_members": "board_id", - "sharing": "id", - } - - subBuilder := s.getQueryBuilder(db). - Select("board_id, MAX(update_at) AS maxDate"). - From(s.tablePrefix + "blocks"). - GroupBy("board_id") - - subQuery, _, _ := subBuilder.ToSql() - - builder := s.getQueryBuilder(db). - Select("id"). - From(s.tablePrefix + "boards"). - LeftJoin("( " + subQuery + " ) As subquery ON (subquery.board_id = id)"). - Where(sq.Lt{"maxDate": globalRetentionDate}). - Where(sq.NotEq{"team_id": "0"}). - Where(sq.Eq{"is_template": false}) - - rows, err := builder.Query() - if err != nil { - s.logger.Error(`dataRetention subquery ERROR`, mlog.Err(err)) - return 0, err - } - defer s.CloseRows(rows) - deleteIds, err := idsFromRows(rows) - if err != nil { - return 0, err - } - - totalAffected := 0 - if len(deleteIds) > 0 { - mlog.Debug("Data Retention DeleteIDs " + strings.Join(deleteIds, ", ")) - for table, field := range deleteTables { - affected, err := s.genericRetentionPoliciesDeletion(db, table, field, deleteIds, batchSize) - if err != nil { - return int64(totalAffected), err - } - totalAffected += int(affected) - } - } - mlog.Info("Complete Boards Data Retention", mlog.Int("total deletion ids", len(deleteIds)), mlog.Int("TotalAffected", totalAffected)) - return int64(totalAffected), nil -} - -func idsFromRows(rows *sql.Rows) ([]string, error) { - deleteIds := []string{} - for rows.Next() { - var boardID string - err := rows.Scan( - &boardID, - ) - if err != nil { - return nil, err - } - deleteIds = append(deleteIds, boardID) - } - return deleteIds, nil -} - -// genericRetentionPoliciesDeletion actually executes the DELETE query using a sq.SelectBuilder -// which selects the rows to delete. -func (s *SQLStore) genericRetentionPoliciesDeletion( - db sq.BaseRunner, - table string, - deleteColumn string, - deleteIds []string, - batchSize int64, -) (int64, error) { - whereClause := deleteColumn + ` IN ('` + strings.Join(deleteIds, `','`) + `')` - deleteQuery := s.getQueryBuilder(db). - Delete(s.tablePrefix + table). - Where(whereClause) - s1, _, _ := deleteQuery.ToSql() - mlog.Debug(s1) - - var totalRowsAffected int64 - var batchRowsAffected int64 - for { - result, err := deleteQuery.Exec() - if err != nil { - return 0, errors.Wrap(err, "failed to delete "+table) - } - - batchRowsAffected, err = result.RowsAffected() - if err != nil { - return 0, errors.Wrap(err, "failed to get rows affected for "+table) - } - totalRowsAffected += batchRowsAffected - if batchRowsAffected != batchSize { - break - } - } - - mlog.Debug("Rows Affected" + strconv.FormatInt(totalRowsAffected, 10)) - return totalRowsAffected, nil -} - func (s *SQLStore) duplicateBlock(db sq.BaseRunner, boardID string, blockID string, userID string, asTemplate bool) ([]model.Block, error) { blocks, err := s.getSubTree2(db, boardID, blockID, model.QuerySubtreeOptions{}) if err != nil { diff --git a/server/services/store/sqlstore/params.go b/server/services/store/sqlstore/params.go index 29383fcf0..1a2590a08 100644 --- a/server/services/store/sqlstore/params.go +++ b/server/services/store/sqlstore/params.go @@ -18,7 +18,6 @@ type Params struct { IsPlugin bool NewMutexFn MutexFactory PluginAPI *plugin.API - SkipTemplateInit bool } func (p Params) CheckValid() error { diff --git a/server/services/store/sqlstore/public_methods.go b/server/services/store/sqlstore/public_methods.go index d6e9373f9..e9cbb49fc 100644 --- a/server/services/store/sqlstore/public_methods.go +++ b/server/services/store/sqlstore/public_methods.go @@ -648,30 +648,6 @@ func (s *SQLStore) RemoveDefaultTemplates(boards []*model.Board) error { } -func (s *SQLStore) RunDataRetention(globalRetentionDate int64, batchSize int64) (int64, error) { - if s.dbType == model.SqliteDBType { - return s.runDataRetention(s.db, globalRetentionDate, batchSize) - } - tx, txErr := s.db.BeginTx(context.Background(), nil) - if txErr != nil { - return 0, txErr - } - result, err := s.runDataRetention(tx, globalRetentionDate, batchSize) - if err != nil { - if rollbackErr := tx.Rollback(); rollbackErr != nil { - s.logger.Error("transaction rollback error", mlog.Err(rollbackErr), mlog.String("methodName", "RunDataRetention")) - } - return 0, err - } - - if err := tx.Commit(); err != nil { - return 0, err - } - - return result, nil - -} - func (s *SQLStore) SaveMember(bm *model.BoardMember) (*model.BoardMember, error) { return s.saveMember(s.db, bm) diff --git a/server/services/store/store.go b/server/services/store/store.go index 8530f2bd7..fed38c429 100644 --- a/server/services/store/store.go +++ b/server/services/store/store.go @@ -134,9 +134,6 @@ type Store interface { RemoveDefaultTemplates(boards []*model.Board) error GetTemplateBoards(teamID, userID string) ([]*model.Board, error) - // @withTransaction - RunDataRetention(globalRetentionDate int64, batchSize int64) (int64, error) - DBType() string IsErrNotFound(err error) bool diff --git a/server/services/store/storetests/blocks.go b/server/services/store/storetests/blocks.go index ba694e334..5f155db07 100644 --- a/server/services/store/storetests/blocks.go +++ b/server/services/store/storetests/blocks.go @@ -69,11 +69,6 @@ func StoreTestBlocksStore(t *testing.T, setup func(t *testing.T) (store.Store, f defer tearDown() testDuplicateBlock(t, store) }) - t.Run("RunDataRetention", func(t *testing.T) { - store, tearDown := setup(t) - defer tearDown() - testRunDataRetention(t, store) - }) t.Run("GetBlockMetadata", func(t *testing.T) { store, tearDown := setup(t) defer tearDown() @@ -800,56 +795,6 @@ func testGetBlock(t *testing.T, store store.Store) { }) } -func testRunDataRetention(t *testing.T, store store.Store) { - validBoard := model.Board{ - ID: "board-id-test", - IsTemplate: false, - ModifiedBy: "user-id-1", - TeamID: "team-id", - } - board, err := store.InsertBoard(&validBoard, "user-id-1") - require.NoError(t, err) - - validBlock := model.Block{ - ID: "id-test", - BoardID: board.ID, - ModifiedBy: "user-id-1", - } - - validBlock2 := model.Block{ - ID: "id-test2", - BoardID: board.ID, - ModifiedBy: "user-id-1", - } - - newBlocks := []model.Block{validBlock, validBlock2} - - err = store.InsertBlocks(newBlocks, "user-id-1") - require.NoError(t, err) - - blocks, err := store.GetBlocksWithBoardID(board.ID) - require.NoError(t, err) - require.Len(t, blocks, len(newBlocks)) - initialCount := len(blocks) - - t.Run("test no deletions", func(t *testing.T) { - deletions, err := store.RunDataRetention(utils.GetMillisForTime(time.Now().Add(-time.Hour*1)), 10) - require.NoError(t, err) - require.Equal(t, int64(0), deletions) - }) - - t.Run("test all deletions", func(t *testing.T) { - deletions, err := store.RunDataRetention(utils.GetMillisForTime(time.Now().Add(time.Hour*1)), 10) - require.NoError(t, err) - require.True(t, deletions > int64(initialCount)) - - // expect all blocks to be deleted. - blocks, errBlocks := store.GetBlocksWithBoardID(board.ID) - require.NoError(t, errBlocks) - require.Equal(t, 0, len(blocks)) - }) -} - func testDuplicateBlock(t *testing.T, store store.Store) { InsertBlocks(t, store, subtreeSampleBlocks, "user-id-1") time.Sleep(1 * time.Millisecond)