diff --git a/core/grant/service.go b/core/grant/service.go index 6f2d462f7..4f1ce96e7 100644 --- a/core/grant/service.go +++ b/core/grant/service.go @@ -486,7 +486,7 @@ func (s *Service) ImportFromProvider(ctx context.Context, criteria ImportFromPro func (s *Service) DormancyCheck(ctx context.Context, criteria domain.DormancyCheckCriteria) error { if err := criteria.Validate(); err != nil { - return fmt.Errorf("invalid dormany check criteria: %w", err) + return fmt.Errorf("invalid dormancy check criteria: %w", err) } startDate := time.Now().Add(-criteria.Period) @@ -545,6 +545,7 @@ func (s *Service) DormancyCheck(ctx context.Context, criteria domain.DormancyChe g.ExpirationDateReason = fmt.Sprintf("%s: %s", domain.GrantExpirationReasonDormant, criteria.RetainDuration) newExpDate := time.Now().Add(criteria.RetainDuration) g.ExpirationDate = &newExpDate + g.IsPermanent = false dormantGrants = append(dormantGrants, g) dormantGrantsIDs = append(dormantGrantsIDs, g.ID) diff --git a/core/grant/service_test.go b/core/grant/service_test.go index 4fe5bdf58..82ab4f249 100644 --- a/core/grant/service_test.go +++ b/core/grant/service_test.go @@ -892,3 +892,100 @@ func (s *ServiceTestSuite) TestImportFromProvider() { } }) } + +func (s *ServiceTestSuite) TestDormancyCheck() { + s.Run("should update grants and return nil error on success", func() { + s.setup() + + timeNow := time.Now() + dummyProvider := &domain.Provider{ + ID: "test-provider-id", + } + dummyGrants := []domain.Grant{ + { + ID: "g1", + AccountID: "user@example.com", + Permissions: []string{"role-1"}, + IsPermanent: true, + }, + { + ID: "g2", + AccountID: "user2@example.com", + Permissions: []string{"role-2"}, + }, + } + dummyActivities := []*domain.Activity{} + + dormancyCheckCriteria := domain.DormancyCheckCriteria{ + ProviderID: dummyProvider.ID, + Period: 30 * 24 * time.Hour, // 30 days back + RetainDuration: 7 * 24 * time.Hour, // update grant exp date to 7 days from now + } + + newExpDate := timeNow.Add(dormancyCheckCriteria.RetainDuration) + expectedReason := fmt.Sprintf("%s: %s", domain.GrantExpirationReasonDormant, dormancyCheckCriteria.RetainDuration) + expectedUpdatedGrants := []*domain.Grant{ + { + ID: "g1", + AccountID: "user@example.com", + Permissions: []string{"role-1"}, + ExpirationDate: &newExpDate, + IsPermanent: false, + ExpirationDateReason: expectedReason, + }, + { + ID: "g2", + AccountID: "user2@example.com", + Permissions: []string{"role-2"}, + ExpirationDate: &newExpDate, + ExpirationDateReason: expectedReason, + }, + } + + s.mockProviderService.EXPECT(). + GetByID(mock.AnythingOfType("*context.emptyCtx"), dummyProvider.ID). + Return(dummyProvider, nil).Once() + expectedListGrantsFilter := domain.ListGrantsFilter{ + Statuses: []string{string(domain.GrantStatusActive)}, + ProviderTypes: []string{dummyProvider.Type}, + ProviderURNs: []string{dummyProvider.URN}, + CreatedAtLte: timeNow.Add(-dormancyCheckCriteria.Period), + } + s.mockRepository.EXPECT(). + List(mock.AnythingOfType("*context.emptyCtx"), mock.AnythingOfType("domain.ListGrantsFilter")). + Run(func(_a0 context.Context, f domain.ListGrantsFilter) { + s.Empty(cmp.Diff(expectedListGrantsFilter, f, cmpopts.EquateApproxTime(time.Second))) + }). + Return(dummyGrants, nil).Once() + timestampGte := timeNow.Add(-dormancyCheckCriteria.Period) + expectedListActivitiesFilter := domain.ListActivitiesFilter{ + AccountIDs: []string{"user@example.com", "user2@example.com"}, + TimestampGte: ×tampGte, + } + s.mockProviderService.EXPECT(). + ListActivities(mock.AnythingOfType("*context.emptyCtx"), *dummyProvider, mock.AnythingOfType("domain.ListActivitiesFilter")). + Run(func(_a0 context.Context, _a1 domain.Provider, f domain.ListActivitiesFilter) { + s.Empty(cmp.Diff(expectedListActivitiesFilter, f, + cmpopts.EquateApproxTime(time.Second), + cmpopts.IgnoreUnexported(domain.ListActivitiesFilter{}), + )) + }). + Return(dummyActivities, nil).Once() + s.mockProviderService.EXPECT(). + CorrelateGrantActivities(mock.AnythingOfType("*context.emptyCtx"), *dummyProvider, mock.AnythingOfType("[]*domain.Grant"), dummyActivities). + Return(nil).Once() + s.mockRepository.EXPECT(). + BulkUpsert(mock.AnythingOfType("*context.emptyCtx"), mock.AnythingOfType("[]*domain.Grant")). + Run(func(_a0 context.Context, grants []*domain.Grant) { + s.Empty(cmp.Diff(expectedUpdatedGrants, grants, + cmpopts.EquateApproxTime(time.Second), + )) + }). + Return(nil).Once() + + s.mockNotifier.EXPECT().Notify(mock.Anything).Return(nil).Once() // TODO + + err := s.service.DormancyCheck(context.Background(), dormancyCheckCriteria) + s.NoError(err) + }) +}