diff --git a/models/user/block.go b/models/user/block.go index 6331b754a39..b636d30a249 100644 --- a/models/user/block.go +++ b/models/user/block.go @@ -45,15 +45,20 @@ func UpdateBlockingNote(ctx context.Context, id int64, note string) error { } func IsUserBlockedBy(ctx context.Context, blockee *User, blockerIDs ...int64) bool { - if len(blockerIDs) == 0 { - return false - } - if blockee.IsAdmin { return false } - cond := builder.Eq{"user_blocking.blockee_id": blockee.ID}. + return HasBlocking(ctx, blockee.ID, blockerIDs...) +} + +// HasBlocking reports whether a blocking relationship exists regardless of the blockee's admin status. +func HasBlocking(ctx context.Context, blockeeID int64, blockerIDs ...int64) bool { + if len(blockerIDs) == 0 { + return false + } + + cond := builder.Eq{"user_blocking.blockee_id": blockeeID}. And(builder.In("user_blocking.blocker_id", blockerIDs)) has, _ := db.GetEngine(ctx).Where(cond).Exist(&Blocking{}) diff --git a/services/user/block.go b/services/user/block.go index 19b4dfa5960..5e82e5c0f13 100644 --- a/services/user/block.go +++ b/services/user/block.go @@ -50,7 +50,7 @@ func CanUnblockUser(ctx context.Context, doer, blocker, blockee *user_model.User return false } - if !user_model.IsUserBlockedBy(ctx, blockee, blocker.ID) { + if !user_model.HasBlocking(ctx, blockee.ID, blocker.ID) { return false } diff --git a/services/user/block_test.go b/services/user/block_test.go index dc90ddd7e2c..f97d19ebf7d 100644 --- a/services/user/block_test.go +++ b/services/user/block_test.go @@ -62,4 +62,8 @@ func TestCanUnblockUser(t *testing.T) { assert.True(t, CanUnblockUser(t.Context(), user1, user2, user29)) assert.True(t, CanUnblockUser(t.Context(), user2, user2, user29)) assert.True(t, CanUnblockUser(t.Context(), user1, org17, user28)) + // Existing block can still be removed after the blockee becomes an admin. + user29.IsAdmin = true + assert.False(t, user_model.IsUserBlockedBy(t.Context(), user29, user2.ID)) + assert.True(t, CanUnblockUser(t.Context(), user2, user2, user29)) }