diff --git a/management/server/group.go b/management/server/group.go index d0d6d2628..3cd31f152 100644 --- a/management/server/group.go +++ b/management/server/group.go @@ -256,6 +256,7 @@ func (am *DefaultAccountManager) CreateGroups(ctx context.Context, accountID, us for _, newGroup := range groups { change := affectedpeers.Change{ChangedGroupIDs: []string{newGroup.ID}} var snap *affectedpeers.Snapshot + var events []func() err = am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error { if err = validateNewGroup(ctx, transaction, accountID, newGroup); err != nil { return err @@ -263,6 +264,7 @@ func (am *DefaultAccountManager) CreateGroups(ctx context.Context, accountID, us newGroup.AccountID = accountID newGroup.PublicID = xid.New().String() + events = am.prepareGroupEvents(ctx, transaction, accountID, userID, newGroup) if err = transaction.CreateGroup(ctx, newGroup); err != nil { return err @@ -273,9 +275,6 @@ func (am *DefaultAccountManager) CreateGroups(ctx context.Context, accountID, us return err } - events := am.prepareGroupEvents(ctx, transaction, accountID, userID, newGroup) - eventsToStore = append(eventsToStore, events...) - snap, err = affectedpeers.Load(ctx, transaction, accountID, change) return err }) @@ -290,6 +289,7 @@ func (am *DefaultAccountManager) CreateGroups(ctx context.Context, accountID, us } createdCount++ affected.add(snap.Expand(ctx, accountID, change)) + eventsToStore = append(eventsToStore, events...) } for _, storeEvent := range eventsToStore { @@ -358,6 +358,8 @@ func (am *DefaultAccountManager) updateSingleGroup(ctx context.Context, accountI } newGroup.PublicID = oldGroup.PublicID + events = am.prepareGroupEvents(ctx, transaction, accountID, userID, newGroup) + if err := transaction.UpdateGroup(ctx, newGroup); err != nil { return err } @@ -372,8 +374,6 @@ func (am *DefaultAccountManager) updateSingleGroup(ctx context.Context, accountI return err } - events = am.prepareGroupEvents(ctx, transaction, accountID, userID, newGroup) - snap, err = affectedpeers.Load(ctx, transaction, accountID, change) return err }) diff --git a/management/server/group_test.go b/management/server/group_test.go index 61ba56c44..9bcebfd34 100644 --- a/management/server/group_test.go +++ b/management/server/group_test.go @@ -20,6 +20,7 @@ import ( nbdns "github.com/netbirdio/netbird/dns" agentNetworkTypes "github.com/netbirdio/netbird/management/internals/modules/agentnetwork/types" rpservice "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/service" + "github.com/netbirdio/netbird/management/server/activity" "github.com/netbirdio/netbird/management/server/groups" "github.com/netbirdio/netbird/management/server/networks" "github.com/netbirdio/netbird/management/server/networks/resources" @@ -77,6 +78,42 @@ func TestDefaultAccountManager_CreateGroup(t *testing.T) { } } +func TestDefaultAccountManager_BatchGroupChangesStoreEvents(t *testing.T) { + t.Setenv("NB_EVENT_ACTIVITY_LOG_ENABLED", "true") + + am, _, err := createManager(t) + require.NoError(t, err) + + _, account, err := initTestGroupAccount(am) + require.NoError(t, err) + + group := &types.Group{ID: "grp-batch", Name: "Batch group", Issued: types.GroupIssuedAPI} + err = am.CreateGroups(context.Background(), account.Id, groupAdminUserID, []*types.Group{group}) + require.NoError(t, err) + + renamed := &types.Group{ID: group.ID, Name: "Batch group renamed", Issued: types.GroupIssuedAPI} + err = am.UpdateGroups(context.Background(), account.Id, groupAdminUserID, []*types.Group{renamed}) + require.NoError(t, err) + + hasEvent := func(code activity.Activity) bool { + events, err := am.eventStore.Get(context.Background(), account.Id, 0, 100, true) + if err != nil { + return false + } + for _, event := range events { + if event.Activity == code && event.TargetID == group.ID { + return true + } + } + return false + } + + assert.Eventually(t, func() bool { return hasEvent(activity.GroupCreated) }, time.Second, 10*time.Millisecond, + "CreateGroups should store a group created event") + assert.Eventually(t, func() bool { return hasEvent(activity.GroupUpdated) }, time.Second, 10*time.Millisecond, + "UpdateGroups should store a group updated event on rename") +} + func TestDefaultAccountManager_DeleteGroup(t *testing.T) { am, _, err := createManager(t) if err != nil { @@ -1085,7 +1122,6 @@ func Test_AddPeerToGroup(t *testing.T) { errs <- fmt.Errorf("AddPeer failed for peer %d: %w", i, err) return } - }(i) } startTime := time.Now() @@ -1142,7 +1178,6 @@ func Test_AddPeerToAll(t *testing.T) { errs <- fmt.Errorf("AddPeer failed for peer %d: %w", i, err) return } - }(i) } startTime := time.Now()