From c1787d06e2917e75eb8901ac0586abb34a54f669 Mon Sep 17 00:00:00 2001 From: Gusted Date: Tue, 17 Mar 2026 09:11:52 +0100 Subject: [PATCH] fix: add missing deleting beans for organizations (#11699) - Delete blocked users entries. - Organization cannot get blocked, it can block other people however. - Delete following entries. - Organization cannot follow, it can be followed by users. - Resolves forgejo/forgejo#11416 Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11699 Reviewed-by: Mathieu Fenniak Reviewed-by: 0ko <0ko@noreply.codeberg.org> Reviewed-by: Andreas Ahlenstorf Co-authored-by: Gusted Co-committed-by: Gusted --- models/organization/org.go | 10 ++++++++++ release-notes/11699.md | 1 + services/org/TestDeleteOrganization/follow.yml | 4 ++++ .../TestDeleteOrganization/forgejo_blocked_user.yml | 5 +++++ services/org/TestDeleteOrganization/user.yml | 13 +++++++++++++ services/org/org_test.go | 4 ++++ 6 files changed, 37 insertions(+) create mode 100644 release-notes/11699.md create mode 100644 services/org/TestDeleteOrganization/follow.yml create mode 100644 services/org/TestDeleteOrganization/forgejo_blocked_user.yml create mode 100644 services/org/TestDeleteOrganization/user.yml diff --git a/models/organization/org.go b/models/organization/org.go index 7dcb78cb9b..02794ba2cb 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -397,6 +397,14 @@ func DeleteOrganization(ctx context.Context, org *Organization) error { return fmt.Errorf("%s is a user not an organization", org.Name) } + // Decrease following count of users that follow the organisation. + followerIDs, err := db.FindIDs(ctx, "follow", "follow.user_id", builder.Eq{"follow.follow_id": org.ID}) + if err != nil { + return fmt.Errorf("get all followers: %w", err) + } else if err = db.DecrByIDs(ctx, followerIDs, "num_following", new(user_model.User)); err != nil { + return fmt.Errorf("decrease user num_following: %w", err) + } + if err := db.DeleteBeans(ctx, &Team{OrgID: org.ID}, &OrgUser{OrgID: org.ID}, @@ -406,6 +414,8 @@ func DeleteOrganization(ctx context.Context, org *Organization) error { &secret_model.Secret{OwnerID: org.ID}, &actions_model.ActionRunner{OwnerID: org.ID}, &actions_model.ActionRunnerToken{OwnerID: optional.Some(org.ID)}, + &user_model.BlockedUser{UserID: org.ID}, + &user_model.Follow{FollowID: org.ID}, ); err != nil { return fmt.Errorf("DeleteBeans: %w", err) } diff --git a/release-notes/11699.md b/release-notes/11699.md new file mode 100644 index 0000000000..8ecf708442 --- /dev/null +++ b/release-notes/11699.md @@ -0,0 +1 @@ +fix: The DB entries about users following an organization and users blocked by an organization were not deleted when an organization was deleted. Orphaned entries can be cleaned up by running `forgejo doctor check --run check-db-consistency --fix`. diff --git a/services/org/TestDeleteOrganization/follow.yml b/services/org/TestDeleteOrganization/follow.yml new file mode 100644 index 0000000000..7677806934 --- /dev/null +++ b/services/org/TestDeleteOrganization/follow.yml @@ -0,0 +1,4 @@ +- + id: 1001 + user_id: 1001 + follow_id: 6 diff --git a/services/org/TestDeleteOrganization/forgejo_blocked_user.yml b/services/org/TestDeleteOrganization/forgejo_blocked_user.yml new file mode 100644 index 0000000000..f1281fb65d --- /dev/null +++ b/services/org/TestDeleteOrganization/forgejo_blocked_user.yml @@ -0,0 +1,5 @@ +- + id: 1001 + user_id: 6 + block_id: 1 + created_unix: 1772018142 diff --git a/services/org/TestDeleteOrganization/user.yml b/services/org/TestDeleteOrganization/user.yml new file mode 100644 index 0000000000..cb1ac4138f --- /dev/null +++ b/services/org/TestDeleteOrganization/user.yml @@ -0,0 +1,13 @@ +- + id: 1001 + lower_name: user1001 + name: user1001 + full_name: User That loves Upper Cases + email: AnotherTestUserWithUpperCaseEmail@otto.splvs.net + passwd: ZogKvWdyEx:password + passwd_hash_algo: dummy + avatar: '' + avatar_email: anothertestuserwithuppercaseemail@otto.splvs.net + login_name: user1 + created_unix: 1772018142 + num_following: 1 diff --git a/services/org/org_test.go b/services/org/org_test.go index 38736286f4..fdb7f14008 100644 --- a/services/org/org_test.go +++ b/services/org/org_test.go @@ -32,6 +32,8 @@ func TestDeleteOrganization(t *testing.T) { unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6}) unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6}) unittest.AssertNotExistsBean(t, &actions.ActionRunnerToken{OwnerID: optional.Some[int64](6)}) + unittest.AssertNotExistsBean(t, &user_model.Follow{FollowID: 6}) + unittest.AssertNotExistsBean(t, &user_model.BlockedUser{UserID: 6}) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) err := DeleteOrganization(db.DefaultContext, org, false) @@ -41,4 +43,6 @@ func TestDeleteOrganization(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) require.Error(t, DeleteOrganization(db.DefaultContext, user, false)) unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) + + assert.Zero(t, unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1001}).NumFollowing) }