diff --git a/api/src/main/java/run/halo/app/core/extension/AuthProvider.java b/api/src/main/java/run/halo/app/core/extension/AuthProvider.java index 0dce286ab..e3360d475 100644 --- a/api/src/main/java/run/halo/app/core/extension/AuthProvider.java +++ b/api/src/main/java/run/halo/app/core/extension/AuthProvider.java @@ -23,6 +23,8 @@ import run.halo.app.extension.GVK; singular = "authprovider", plural = "authproviders") public class AuthProvider extends AbstractExtension { + public static final String PRIVILEGED_LABEL = "auth.halo.run/privileged"; + @Schema(requiredMode = REQUIRED) private AuthProviderSpec spec; diff --git a/application/src/main/java/run/halo/app/security/AuthProviderServiceImpl.java b/application/src/main/java/run/halo/app/security/AuthProviderServiceImpl.java index f9136eab8..e4467eaf3 100644 --- a/application/src/main/java/run/halo/app/security/AuthProviderServiceImpl.java +++ b/application/src/main/java/run/halo/app/security/AuthProviderServiceImpl.java @@ -9,6 +9,7 @@ import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.lang.NonNull; 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.UserConnection; import run.halo.app.extension.ConfigMap; +import run.halo.app.extension.MetadataUtil; import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.infra.SystemSetting; import run.halo.app.infra.utils.JsonUtils; @@ -104,13 +106,28 @@ public class AuthProviderServiceImpl implements AuthProviderService { return client.fetch(ConfigMap.class, SystemSetting.SYSTEM_CONFIG) .flatMap(configMap -> { SystemSetting.AuthProvider authProvider = getAuthProvider(configMap); - final Map data = configMap.getData(); consumer.accept(authProvider.getEnabled()); - data.put(SystemSetting.AuthProvider.GROUP, JsonUtils.objectToJson(authProvider)); - return client.update(configMap); + return fetchPrivilegedProviders() + .doOnNext(privileged -> { + authProvider.getEnabled().addAll(privileged); + }) + .then(Mono.defer(() -> { + final Map data = configMap.getData(); + data.put(SystemSetting.AuthProvider.GROUP, + JsonUtils.objectToJson(authProvider)); + return client.update(configMap); + })); }); } + private Mono> fetchPrivilegedProviders() { + return client.list(AuthProvider.class, + provider -> privileged(provider), + null) + .map(provider -> provider.getMetadata().getName()) + .collectList(); + } + private ListedAuthProvider convertTo(AuthProvider authProvider) { return ListedAuthProvider.builder() .name(authProvider.getMetadata().getName()) @@ -124,9 +141,15 @@ public class AuthProviderServiceImpl implements AuthProviderService { .unbindingUrl(authProvider.getSpec().getUnbindUrl()) .isBound(false) .enabled(false) + .privileged(privileged(authProvider)) .build(); } + private boolean privileged(AuthProvider authProvider) { + return BooleanUtils.TRUE.equals(MetadataUtil.nullSafeLabels(authProvider) + .get(AuthProvider.PRIVILEGED_LABEL)); + } + @NonNull private static SystemSetting.AuthProvider getAuthProvider(ConfigMap configMap) { if (configMap.getData() == null) { @@ -146,8 +169,6 @@ public class AuthProviderServiceImpl implements AuthProviderService { if (authProvider.getEnabled() == null) { authProvider.setEnabled(new HashSet<>()); } - // default enable local auth provider - authProvider.getEnabled().add("local"); return authProvider; } } diff --git a/application/src/main/java/run/halo/app/security/ListedAuthProvider.java b/application/src/main/java/run/halo/app/security/ListedAuthProvider.java index 59b2855ec..3c2edb568 100644 --- a/application/src/main/java/run/halo/app/security/ListedAuthProvider.java +++ b/application/src/main/java/run/halo/app/security/ListedAuthProvider.java @@ -38,4 +38,6 @@ public class ListedAuthProvider { Boolean isBound; Boolean enabled; + + Boolean privileged; } diff --git a/application/src/main/resources/extensions/authproviders.yaml b/application/src/main/resources/extensions/authproviders.yaml index 3f2997762..ff49d88cb 100644 --- a/application/src/main/resources/extensions/authproviders.yaml +++ b/application/src/main/resources/extensions/authproviders.yaml @@ -2,6 +2,8 @@ apiVersion: auth.halo.run/v1alpha1 kind: AuthProvider metadata: name: local + labels: + auth.halo.run/privileged: "true" finalizers: - system-protection spec: diff --git a/application/src/test/java/run/halo/app/security/AuthProviderServiceImplTest.java b/application/src/test/java/run/halo/app/security/AuthProviderServiceImplTest.java index 255d7f5b9..a93673062 100644 --- a/application/src/test/java/run/halo/app/security/AuthProviderServiceImplTest.java +++ b/application/src/test/java/run/halo/app/security/AuthProviderServiceImplTest.java @@ -57,6 +57,10 @@ class AuthProviderServiceImplTest { when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG))) .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 Mono result = authProviderService.enable("github"); @@ -78,6 +82,10 @@ class AuthProviderServiceImplTest { AuthProvider authProvider = createAuthProvider("github"); 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 captor = ArgumentCaptor.forClass(ConfigMap.class); when(client.update(captor.capture())).thenReturn(Mono.empty()); @@ -135,19 +143,22 @@ class AuthProviderServiceImplTest { "displayName": "github", "bindingUrl": "fake-binding-url", "enabled": true, - "isBound": false + "isBound": false, + "privileged": false }, { "name": "gitlab", "displayName": "gitlab", "bindingUrl": "fake-binding-url", "enabled": false, - "isBound": false + "isBound": false, + "privileged": false },{ - + "name": "gitee", "displayName": "gitee", "enabled": false, - "isBound": false + "isBound": false, + "privileged": false }] """, JsonUtils.objectToJson(result), @@ -163,6 +174,7 @@ class AuthProviderServiceImplTest { AuthProvider authProvider = new AuthProvider(); authProvider.setMetadata(new Metadata()); authProvider.getMetadata().setName(name); + authProvider.getMetadata().setLabels(new HashMap<>()); authProvider.setSpec(new AuthProvider.AuthProviderSpec()); authProvider.getSpec().setDisplayName(name); return authProvider; diff --git a/console/packages/api-client/src/models/listed-auth-provider.ts b/console/packages/api-client/src/models/listed-auth-provider.ts index ac5cb482f..fb5b1b0a8 100644 --- a/console/packages/api-client/src/models/listed-auth-provider.ts +++ b/console/packages/api-client/src/models/listed-auth-provider.ts @@ -72,6 +72,12 @@ export interface ListedAuthProvider { * @memberof ListedAuthProvider */ name: string; + /** + * + * @type {boolean} + * @memberof ListedAuthProvider + */ + privileged?: boolean; /** * * @type {string} diff --git a/console/src/locales/en.yaml b/console/src/locales/en.yaml index 5910e05de..4f38f68cb 100644 --- a/console/src/locales/en.yaml +++ b/console/src/locales/en.yaml @@ -870,6 +870,8 @@ core: title: Are you sure you want to enable this identity authentication method? disable: 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: fields: display_name: Display name diff --git a/console/src/locales/zh-CN.yaml b/console/src/locales/zh-CN.yaml index c5157fdf5..174faead1 100644 --- a/console/src/locales/zh-CN.yaml +++ b/console/src/locales/zh-CN.yaml @@ -870,6 +870,8 @@ core: title: 确定要启用该身份认证方式吗? disable: title: 确定要停用该身份认证方式吗? + disable_privileged: + tooltip: 系统保留的认证方式,无法禁用 detail: fields: display_name: 名称 diff --git a/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue b/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue index ca69839c0..371d5172f 100644 --- a/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue +++ b/console/src/modules/system/auth-providers/components/AuthProviderListItem.vue @@ -76,11 +76,18 @@ const handleChangeStatus = async () => {