perf: hide the switch of local identity authentication (#3562)

#### What type of PR is this?

/kind improvement
/area console 

#### What this PR does / why we need it:

在身份认证的列表中隐藏本地身份认证的启用/禁用开关。

<img width="1402" alt="image" src="https://user-images.githubusercontent.com/21301288/226804384-e12ea447-d7ad-4429-82bc-2621fcca84dc.png">

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

Fixes #3557 

#### Does this PR introduce a user-facing change?

```release-note
None 
```
pull/3561/head
Ryan Wang 2023-03-27 16:02:20 +08:00 committed by GitHub
parent 5b3b473cb3
commit fbe8e627e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 66 additions and 10 deletions

View File

@ -23,6 +23,8 @@ import run.halo.app.extension.GVK;
singular = "authprovider", plural = "authproviders") singular = "authprovider", plural = "authproviders")
public class AuthProvider extends AbstractExtension { public class AuthProvider extends AbstractExtension {
public static final String PRIVILEGED_LABEL = "auth.halo.run/privileged";
@Schema(requiredMode = REQUIRED) @Schema(requiredMode = REQUIRED)
private AuthProviderSpec spec; private AuthProviderSpec spec;

View File

@ -9,6 +9,7 @@ import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.security.core.context.ReactiveSecurityContextHolder;
@ -18,6 +19,7 @@ import reactor.core.publisher.Mono;
import run.halo.app.core.extension.AuthProvider; import run.halo.app.core.extension.AuthProvider;
import run.halo.app.core.extension.UserConnection; import run.halo.app.core.extension.UserConnection;
import run.halo.app.extension.ConfigMap; import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.SystemSetting; import run.halo.app.infra.SystemSetting;
import run.halo.app.infra.utils.JsonUtils; import run.halo.app.infra.utils.JsonUtils;
@ -104,13 +106,28 @@ public class AuthProviderServiceImpl implements AuthProviderService {
return client.fetch(ConfigMap.class, SystemSetting.SYSTEM_CONFIG) return client.fetch(ConfigMap.class, SystemSetting.SYSTEM_CONFIG)
.flatMap(configMap -> { .flatMap(configMap -> {
SystemSetting.AuthProvider authProvider = getAuthProvider(configMap); SystemSetting.AuthProvider authProvider = getAuthProvider(configMap);
final Map<String, String> data = configMap.getData();
consumer.accept(authProvider.getEnabled()); consumer.accept(authProvider.getEnabled());
data.put(SystemSetting.AuthProvider.GROUP, JsonUtils.objectToJson(authProvider)); 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); return client.update(configMap);
}));
}); });
} }
private Mono<List<String>> fetchPrivilegedProviders() {
return client.list(AuthProvider.class,
provider -> privileged(provider),
null)
.map(provider -> provider.getMetadata().getName())
.collectList();
}
private ListedAuthProvider convertTo(AuthProvider authProvider) { private ListedAuthProvider convertTo(AuthProvider authProvider) {
return ListedAuthProvider.builder() return ListedAuthProvider.builder()
.name(authProvider.getMetadata().getName()) .name(authProvider.getMetadata().getName())
@ -124,9 +141,15 @@ public class AuthProviderServiceImpl implements AuthProviderService {
.unbindingUrl(authProvider.getSpec().getUnbindUrl()) .unbindingUrl(authProvider.getSpec().getUnbindUrl())
.isBound(false) .isBound(false)
.enabled(false) .enabled(false)
.privileged(privileged(authProvider))
.build(); .build();
} }
private boolean privileged(AuthProvider authProvider) {
return BooleanUtils.TRUE.equals(MetadataUtil.nullSafeLabels(authProvider)
.get(AuthProvider.PRIVILEGED_LABEL));
}
@NonNull @NonNull
private static SystemSetting.AuthProvider getAuthProvider(ConfigMap configMap) { private static SystemSetting.AuthProvider getAuthProvider(ConfigMap configMap) {
if (configMap.getData() == null) { if (configMap.getData() == null) {
@ -146,8 +169,6 @@ public class AuthProviderServiceImpl implements AuthProviderService {
if (authProvider.getEnabled() == null) { if (authProvider.getEnabled() == null) {
authProvider.setEnabled(new HashSet<>()); authProvider.setEnabled(new HashSet<>());
} }
// default enable local auth provider
authProvider.getEnabled().add("local");
return authProvider; return authProvider;
} }
} }

View File

@ -38,4 +38,6 @@ public class ListedAuthProvider {
Boolean isBound; Boolean isBound;
Boolean enabled; Boolean enabled;
Boolean privileged;
} }

View File

@ -2,6 +2,8 @@ apiVersion: auth.halo.run/v1alpha1
kind: AuthProvider kind: AuthProvider
metadata: metadata:
name: local name: local
labels:
auth.halo.run/privileged: "true"
finalizers: finalizers:
- system-protection - system-protection
spec: spec:

View File

@ -57,6 +57,10 @@ class AuthProviderServiceImplTest {
when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG))) when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG)))
.thenReturn(Mono.just(configMap)); .thenReturn(Mono.just(configMap));
AuthProvider local = createAuthProvider("local");
local.getMetadata().getLabels().put(AuthProvider.PRIVILEGED_LABEL, "true");
when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
// Call the method being tested // Call the method being tested
Mono<AuthProvider> result = authProviderService.enable("github"); Mono<AuthProvider> result = authProviderService.enable("github");
@ -78,6 +82,10 @@ class AuthProviderServiceImplTest {
AuthProvider authProvider = createAuthProvider("github"); AuthProvider authProvider = createAuthProvider("github");
when(client.get(eq(AuthProvider.class), eq("github"))).thenReturn(Mono.just(authProvider)); when(client.get(eq(AuthProvider.class), eq("github"))).thenReturn(Mono.just(authProvider));
AuthProvider local = createAuthProvider("local");
local.getMetadata().getLabels().put(AuthProvider.PRIVILEGED_LABEL, "true");
when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
ArgumentCaptor<ConfigMap> captor = ArgumentCaptor.forClass(ConfigMap.class); ArgumentCaptor<ConfigMap> captor = ArgumentCaptor.forClass(ConfigMap.class);
when(client.update(captor.capture())).thenReturn(Mono.empty()); when(client.update(captor.capture())).thenReturn(Mono.empty());
@ -135,19 +143,22 @@ class AuthProviderServiceImplTest {
"displayName": "github", "displayName": "github",
"bindingUrl": "fake-binding-url", "bindingUrl": "fake-binding-url",
"enabled": true, "enabled": true,
"isBound": false "isBound": false,
"privileged": false
}, { }, {
"name": "gitlab", "name": "gitlab",
"displayName": "gitlab", "displayName": "gitlab",
"bindingUrl": "fake-binding-url", "bindingUrl": "fake-binding-url",
"enabled": false, "enabled": false,
"isBound": false "isBound": false,
"privileged": false
},{ },{
"name": "gitee", "name": "gitee",
"displayName": "gitee", "displayName": "gitee",
"enabled": false, "enabled": false,
"isBound": false "isBound": false,
"privileged": false
}] }]
""", """,
JsonUtils.objectToJson(result), JsonUtils.objectToJson(result),
@ -163,6 +174,7 @@ class AuthProviderServiceImplTest {
AuthProvider authProvider = new AuthProvider(); AuthProvider authProvider = new AuthProvider();
authProvider.setMetadata(new Metadata()); authProvider.setMetadata(new Metadata());
authProvider.getMetadata().setName(name); authProvider.getMetadata().setName(name);
authProvider.getMetadata().setLabels(new HashMap<>());
authProvider.setSpec(new AuthProvider.AuthProviderSpec()); authProvider.setSpec(new AuthProvider.AuthProviderSpec());
authProvider.getSpec().setDisplayName(name); authProvider.getSpec().setDisplayName(name);
return authProvider; return authProvider;

View File

@ -72,6 +72,12 @@ export interface ListedAuthProvider {
* @memberof ListedAuthProvider * @memberof ListedAuthProvider
*/ */
name: string; name: string;
/**
*
* @type {boolean}
* @memberof ListedAuthProvider
*/
privileged?: boolean;
/** /**
* *
* @type {string} * @type {string}

View File

@ -870,6 +870,8 @@ core:
title: Are you sure you want to enable this identity authentication method? title: Are you sure you want to enable this identity authentication method?
disable: disable:
title: Are you sure you want to disable this identity authentication method? title: Are you sure you want to disable this identity authentication method?
disable_privileged:
tooltip: The authentication method reserved by the system cannot be disabled
detail: detail:
fields: fields:
display_name: Display name display_name: Display name

View File

@ -870,6 +870,8 @@ core:
title: 确定要启用该身份认证方式吗? title: 确定要启用该身份认证方式吗?
disable: disable:
title: 确定要停用该身份认证方式吗? title: 确定要停用该身份认证方式吗?
disable_privileged:
tooltip: 系统保留的认证方式,无法禁用
detail: detail:
fields: fields:
display_name: 名称 display_name: 名称

View File

@ -76,11 +76,18 @@ const handleChangeStatus = async () => {
</VEntityField> </VEntityField>
</template> </template>
<template #end> <template #end>
<VEntityField v-permission="['system:plugins:manage']"> <VEntityField>
<template #description> <template #description>
<div class="flex items-center"> <div class="flex items-center">
<VSwitch <VSwitch
v-tooltip="{
disabled: !authProvider.privileged,
content: $t(
'core.identity_authentication.operations.disable_privileged.tooltip'
),
}"
:model-value="authProvider.enabled" :model-value="authProvider.enabled"
:disabled="authProvider.privileged"
@click="handleChangeStatus" @click="handleChangeStatus"
/> />
</div> </div>