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 <mfenniak@noreply.codeberg.org>
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
Gusted 2026-03-17 09:11:52 +01:00 committed by Gusted
parent 075ee9ea88
commit c1787d06e2
6 changed files with 37 additions and 0 deletions

View file

@ -397,6 +397,14 @@ func DeleteOrganization(ctx context.Context, org *Organization) error {
return fmt.Errorf("%s is a user not an organization", org.Name) 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, if err := db.DeleteBeans(ctx,
&Team{OrgID: org.ID}, &Team{OrgID: org.ID},
&OrgUser{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}, &secret_model.Secret{OwnerID: org.ID},
&actions_model.ActionRunner{OwnerID: org.ID}, &actions_model.ActionRunner{OwnerID: org.ID},
&actions_model.ActionRunnerToken{OwnerID: optional.Some(org.ID)}, &actions_model.ActionRunnerToken{OwnerID: optional.Some(org.ID)},
&user_model.BlockedUser{UserID: org.ID},
&user_model.Follow{FollowID: org.ID},
); err != nil { ); err != nil {
return fmt.Errorf("DeleteBeans: %w", err) return fmt.Errorf("DeleteBeans: %w", err)
} }

1
release-notes/11699.md Normal file
View file

@ -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`.

View file

@ -0,0 +1,4 @@
-
id: 1001
user_id: 1001
follow_id: 6

View file

@ -0,0 +1,5 @@
-
id: 1001
user_id: 6
block_id: 1
created_unix: 1772018142

View file

@ -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

View file

@ -32,6 +32,8 @@ func TestDeleteOrganization(t *testing.T) {
unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6}) unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6})
unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6}) unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6})
unittest.AssertNotExistsBean(t, &actions.ActionRunnerToken{OwnerID: optional.Some[int64](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}) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
err := DeleteOrganization(db.DefaultContext, org, false) err := DeleteOrganization(db.DefaultContext, org, false)
@ -41,4 +43,6 @@ func TestDeleteOrganization(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5})
require.Error(t, DeleteOrganization(db.DefaultContext, user, false)) require.Error(t, DeleteOrganization(db.DefaultContext, user, false))
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{})
assert.Zero(t, unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1001}).NumFollowing)
} }