refactor: delete dependent userconnection resources when an user is deleted (#3640)

#### What type of PR is this?
/kind improvement
/area core
/milestone 2.4.0

#### What this PR does / why we need it:
当用户被删除时关联删除用户的绑定账号信息

how to test it?
1. 创建用户
2. 绑定账号
3. 使用管理员删除此用户并查看关联的 UserConnection 是否被删除
```shell
curl -u 'your-username:your-password' http://127.0.0.1:8090/apis/auth.halo.run/v1alpha1/userconnections | jq  -r '.'
```
#### Which issue(s) this PR fixes:
Fixes #3639

#### Does this PR introduce a user-facing change?
```release-note
None
```
pull/3608/head^2
guqing 2023-03-30 23:40:19 +08:00 committed by GitHub
parent ff466f5de6
commit 7b43d21866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 28 additions and 2 deletions

View File

@ -1,13 +1,15 @@
package run.halo.app.core.extension.reconciler;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component;
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.UserConnection;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.controller.Controller;
import run.halo.app.extension.controller.ControllerBuilder;
@ -23,8 +25,12 @@ import run.halo.app.infra.utils.PathUtils;
public class UserReconciler implements Reconciler<Request> {
private static final String FINALIZER_NAME = "user-protection";
private final ExtensionClient client;
private final ApplicationEventPublisher eventPublisher;
private final ExternalUrlSupplier externalUrlSupplier;
private final RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(20)
.fixedBackoff(300)
.retryOn(IllegalStateException.class)
.build();
@Override
public Result reconcile(Request request) {
@ -85,6 +91,10 @@ public class UserReconciler implements Reconciler<Request> {
private void cleanUpResourcesAndRemoveFinalizer(String userName) {
client.fetch(User.class, userName).ifPresent(user -> {
// wait for dependent resources to be deleted
deleteUserConnections(userName);
// remove finalizer
if (user.getMetadata().getFinalizers() != null) {
user.getMetadata().getFinalizers().remove(FINALIZER_NAME);
}
@ -92,6 +102,22 @@ public class UserReconciler implements Reconciler<Request> {
});
}
void deleteUserConnections(String userName) {
listConnectionsByUsername(userName).forEach(client::delete);
// wait for user connection to be deleted
retryTemplate.execute(callback -> {
if (listConnectionsByUsername(userName).size() > 0) {
throw new IllegalStateException("User connection is not deleted yet");
}
return null;
});
}
List<UserConnection> listConnectionsByUsername(String username) {
return client.list(UserConnection.class,
connection -> connection.getSpec().getUsername().equals(username), null);
}
@Override
public Controller setupWith(ControllerBuilder builder) {
return builder