fix: initialization status of the privileged auth provider is OFF (#3627)

#### What type of PR is this?
/kind feature
/area core
/milestone 2.4.x

#### What this PR does / why we need it:
修复 Local 认证方式的开关初始化状态为关闭

#### Which issue(s) this PR fixes:
Fixes #3602

#### Does this PR introduce a user-facing change?
```release-note
None
```
pull/3626/head
guqing 2023-03-30 16:42:14 +08:00 committed by GitHub
parent d355e797bd
commit 520074bd9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 21 deletions

View File

@ -0,0 +1,90 @@
package run.halo.app.core.extension.reconciler;
import java.util.HashSet;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.stereotype.Component;
import run.halo.app.core.extension.AuthProvider;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.controller.Controller;
import run.halo.app.extension.controller.ControllerBuilder;
import run.halo.app.extension.controller.Reconciler;
import run.halo.app.security.AuthProviderService;
/**
* Reconciler for {@link AuthProvider}.
*
* @author guqing
* @since 2.4.0
*/
@Component
@RequiredArgsConstructor
public class AuthProviderReconciler implements Reconciler<Reconciler.Request> {
private static final String FINALIZER_NAME = "auth-provider-protection";
private final ExtensionClient client;
private final AuthProviderService authProviderService;
@Override
public Result reconcile(Request request) {
client.fetch(AuthProvider.class, request.name())
.ifPresent(authProvider -> {
if (authProvider.getMetadata().getDeletionTimestamp() != null) {
removeFinalizer(request.name());
return;
}
addFinalizerIfNecessary(authProvider);
handlePrivileged(authProvider);
});
return Result.doNotRetry();
}
@Override
public Controller setupWith(ControllerBuilder builder) {
return builder
.extension(new AuthProvider())
.build();
}
private void handlePrivileged(AuthProvider authProvider) {
if (privileged(authProvider)) {
authProviderService.enable(authProvider.getMetadata().getName()).block();
}
}
private void addFinalizerIfNecessary(AuthProvider oldAuthProvider) {
Set<String> finalizers = oldAuthProvider.getMetadata().getFinalizers();
if (finalizers != null && finalizers.contains(FINALIZER_NAME)) {
return;
}
client.fetch(AuthProvider.class, oldAuthProvider.getMetadata().getName())
.ifPresent(authProvider -> {
Set<String> newFinalizers = authProvider.getMetadata().getFinalizers();
if (newFinalizers == null) {
newFinalizers = new HashSet<>();
authProvider.getMetadata().setFinalizers(newFinalizers);
}
newFinalizers.add(FINALIZER_NAME);
client.update(authProvider);
});
}
private void removeFinalizer(String authProviderName) {
client.fetch(AuthProvider.class, authProviderName)
.ifPresent(authProvider -> {
// Disable auth provider
authProviderService.disable(authProviderName).block();
if (authProvider.getMetadata().getFinalizers() != null) {
authProvider.getMetadata().getFinalizers().remove(FINALIZER_NAME);
}
client.update(authProvider);
});
}
private boolean privileged(AuthProvider authProvider) {
return BooleanUtils.TRUE.equals(MetadataUtil.nullSafeLabels(authProvider)
.get(AuthProvider.PRIVILEGED_LABEL));
}
}

View File

@ -19,6 +19,7 @@ import reactor.core.publisher.Mono;
import run.halo.app.core.extension.AuthProvider;
import run.halo.app.core.extension.UserConnection;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.SystemSetting;
@ -45,7 +46,9 @@ public class AuthProviderServiceImpl implements AuthProviderService {
@Override
public Mono<AuthProvider> disable(String name) {
// privileged auth provider cannot be disabled
return client.get(AuthProvider.class, name)
.filter(authProvider -> !privileged(authProvider))
.flatMap(authProvider -> updateAuthProviderEnabled(enabled -> enabled.remove(name))
.thenReturn(authProvider)
);
@ -104,28 +107,22 @@ public class AuthProviderServiceImpl implements AuthProviderService {
private Mono<ConfigMap> updateAuthProviderEnabled(Consumer<Set<String>> consumer) {
return client.fetch(ConfigMap.class, SystemSetting.SYSTEM_CONFIG)
.switchIfEmpty(Mono.defer(() -> {
ConfigMap configMap = new ConfigMap();
configMap.setMetadata(new Metadata());
configMap.getMetadata().setName(SystemSetting.SYSTEM_CONFIG);
configMap.setData(new HashMap<>());
return client.create(configMap);
}))
.flatMap(configMap -> {
SystemSetting.AuthProvider authProvider = getAuthProvider(configMap);
consumer.accept(authProvider.getEnabled());
return fetchPrivilegedProviders()
.doOnNext(privileged -> {
authProvider.getEnabled().addAll(privileged);
})
.then(Mono.defer(() -> {
final Map<String, String> data = configMap.getData();
data.put(SystemSetting.AuthProvider.GROUP,
JsonUtils.objectToJson(authProvider));
return client.update(configMap);
}));
});
}
private Mono<List<String>> fetchPrivilegedProviders() {
return client.list(AuthProvider.class,
provider -> privileged(provider),
null)
.map(provider -> provider.getMetadata().getName())
.collectList();
final Map<String, String> data = configMap.getData();
data.put(SystemSetting.AuthProvider.GROUP,
JsonUtils.objectToJson(authProvider));
return client.update(configMap);
});
}
private ListedAuthProvider convertTo(AuthProvider authProvider) {
@ -150,7 +147,7 @@ public class AuthProviderServiceImpl implements AuthProviderService {
return BooleanUtils.TRUE.equals(MetadataUtil.nullSafeLabels(authProvider)
.get(AuthProvider.AUTH_BINDING_LABEL));
}
private boolean privileged(AuthProvider authProvider) {
return BooleanUtils.TRUE.equals(MetadataUtil.nullSafeLabels(authProvider)
.get(AuthProvider.PRIVILEGED_LABEL));

View File

@ -70,7 +70,7 @@ class AuthProviderServiceImplTest {
Set<String> enabled =
JsonUtils.jsonToObject(providerSettingStr, SystemSetting.AuthProvider.class)
.getEnabled();
assertThat(enabled).containsExactly("github", "local");
assertThat(enabled).containsExactly("github");
// Verify the result
verify(client).get(AuthProvider.class, "github");
verify(client).fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG));
@ -104,7 +104,7 @@ class AuthProviderServiceImplTest {
Set<String> enabled =
JsonUtils.jsonToObject(providerSettingStr, SystemSetting.AuthProvider.class)
.getEnabled();
assertThat(enabled).containsExactly("local");
assertThat(enabled).isEmpty();
// Verify the result
verify(client).get(AuthProvider.class, "github");
verify(client).fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG));