diff --git a/api-docs/openapi/v3_0/aggregated.json b/api-docs/openapi/v3_0/aggregated.json index f2242dbd19..d07c4b85c6 100644 --- a/api-docs/openapi/v3_0/aggregated.json +++ b/api-docs/openapi/v3_0/aggregated.json @@ -16034,6 +16034,7 @@ }, "AuthProviderSpec": { "required": [ + "authType", "authenticationUrl", "displayName" ], @@ -16072,10 +16073,6 @@ "method": { "type": "string" }, - "priority": { - "type": "integer", - "format": "int32" - }, "rememberMeSupport": { "type": "boolean" }, @@ -18297,6 +18294,13 @@ ], "type": "object", "properties": { + "authType": { + "type": "string", + "enum": [ + "FORM", + "OAUTH2" + ] + }, "authenticationUrl": { "type": "string" }, @@ -18324,6 +18328,10 @@ "name": { "type": "string" }, + "priority": { + "type": "integer", + "format": "int32" + }, "privileged": { "type": "boolean" }, diff --git a/api-docs/openapi/v3_0/apis_console.api_v1alpha1.json b/api-docs/openapi/v3_0/apis_console.api_v1alpha1.json index ff8db40645..e492fe3dc4 100644 --- a/api-docs/openapi/v3_0/apis_console.api_v1alpha1.json +++ b/api-docs/openapi/v3_0/apis_console.api_v1alpha1.json @@ -3568,6 +3568,7 @@ }, "AuthProviderSpec": { "required": [ + "authType", "authenticationUrl", "displayName" ], @@ -3606,10 +3607,6 @@ "method": { "type": "string" }, - "priority": { - "type": "integer", - "format": "int32" - }, "rememberMeSupport": { "type": "boolean" }, @@ -4435,6 +4432,13 @@ ], "type": "object", "properties": { + "authType": { + "type": "string", + "enum": [ + "FORM", + "OAUTH2" + ] + }, "authenticationUrl": { "type": "string" }, @@ -4462,6 +4466,10 @@ "name": { "type": "string" }, + "priority": { + "type": "integer", + "format": "int32" + }, "privileged": { "type": "boolean" }, diff --git a/api-docs/openapi/v3_0/apis_extension.api_v1alpha1.json b/api-docs/openapi/v3_0/apis_extension.api_v1alpha1.json index 90a36eaf33..84340604dc 100644 --- a/api-docs/openapi/v3_0/apis_extension.api_v1alpha1.json +++ b/api-docs/openapi/v3_0/apis_extension.api_v1alpha1.json @@ -8666,6 +8666,7 @@ }, "AuthProviderSpec": { "required": [ + "authType", "authenticationUrl", "displayName" ], @@ -8704,10 +8705,6 @@ "method": { "type": "string" }, - "priority": { - "type": "integer", - "format": "int32" - }, "rememberMeSupport": { "type": "boolean" }, 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 256072b78a..8cf0aeadb0 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 @@ -6,7 +6,9 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.ToString; +import org.springframework.lang.NonNull; import run.halo.app.extension.AbstractExtension; import run.halo.app.extension.GVK; @@ -55,19 +57,23 @@ public static class AuthProviderSpec { /** * Auth type: form or oauth2. */ - private AuthType authType; + @Getter(onMethod_ = @NonNull) + @Schema(requiredMode = REQUIRED) + private AuthType authType = AuthType.OAUTH2; private String bindingUrl; private String unbindUrl; - private int priority; - @Schema(requiredMode = NOT_REQUIRED) private SettingRef settingRef; @Schema(requiredMode = NOT_REQUIRED) private ConfigMapRef configMapRef; + + public void setAuthType(AuthType authType) { + this.authType = (authType == null ? AuthType.OAUTH2 : authType); + } } @Data @@ -89,7 +95,6 @@ public static class ConfigMapRef { public enum AuthType { FORM, - OAUTH2, - ; + OAUTH2 } } diff --git a/api/src/main/java/run/halo/app/extension/Unstructured.java b/api/src/main/java/run/halo/app/extension/Unstructured.java index 6335fd198c..cf2902ed75 100644 --- a/api/src/main/java/run/halo/app/extension/Unstructured.java +++ b/api/src/main/java/run/halo/app/extension/Unstructured.java @@ -72,7 +72,7 @@ public MetadataOperator getMetadata() { return new UnstructuredMetadata(); } - @EqualsAndHashCode(exclude = "version") + @EqualsAndHashCode(exclude = "tatersion") class UnstructuredMetadata implements MetadataOperator { @Override diff --git a/api/src/main/java/run/halo/app/infra/SystemSetting.java b/api/src/main/java/run/halo/app/infra/SystemSetting.java index 8475cc76eb..6339b54512 100644 --- a/api/src/main/java/run/halo/app/infra/SystemSetting.java +++ b/api/src/main/java/run/halo/app/infra/SystemSetting.java @@ -2,8 +2,9 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.Set; +import java.util.List; import lombok.Data; +import lombok.experimental.Accessors; import org.springframework.boot.convert.ApplicationConversionService; import run.halo.app.extension.ConfigMap; import run.halo.app.infra.utils.JsonUtils; @@ -113,7 +114,15 @@ public static class Menu { @Data public static class AuthProvider { public static final String GROUP = "authProvider"; - private Set enabled; + private List states; + } + + @Data + @Accessors(chain = true) + public static class AuthProviderState { + private String name; + private boolean enabled; + private int priority; } /** diff --git a/application/src/main/java/run/halo/app/security/AuthProviderService.java b/application/src/main/java/run/halo/app/security/AuthProviderService.java index 6bd8093dd9..8b99fd0403 100644 --- a/application/src/main/java/run/halo/app/security/AuthProviderService.java +++ b/application/src/main/java/run/halo/app/security/AuthProviderService.java @@ -19,6 +19,9 @@ public interface AuthProviderService { Mono> listAll(); + /** + * Return a list of enabled AuthProviders sorted by priority. + */ Flux getEnabledProviders(); } 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 d6838bd575..b971b7b255 100644 --- a/application/src/main/java/run/halo/app/security/AuthProviderServiceImpl.java +++ b/application/src/main/java/run/halo/app/security/AuthProviderServiceImpl.java @@ -1,27 +1,31 @@ package run.halo.app.security; +import java.time.Duration; +import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; +import java.util.function.Function; import java.util.stream.Collectors; +import lombok.Data; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.lang.NonNull; import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; +import reactor.util.retry.Retry; 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.ExtensionUtil; import run.halo.app.extension.ListOptions; -import run.halo.app.extension.Metadata; import run.halo.app.extension.MetadataUtil; import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.index.query.QueryFactory; @@ -42,17 +46,17 @@ public class AuthProviderServiceImpl implements AuthProviderService { @Override public Mono enable(String name) { return client.get(AuthProvider.class, name) - .flatMap(authProvider -> updateAuthProviderEnabled(enabled -> enabled.add(name)) + .flatMap(authProvider -> updateAuthProviderEnabled(name, true) .thenReturn(authProvider) ); } @Override public Mono disable(String name) { - // privileged auth provider cannot be disabled return client.get(AuthProvider.class, name) + // privileged auth provider cannot be disabled .filter(authProvider -> !privileged(authProvider)) - .flatMap(authProvider -> updateAuthProviderEnabled(enabled -> enabled.remove(name)) + .flatMap(authProvider -> updateAuthProviderEnabled(name, false) .thenReturn(authProvider) ); } @@ -62,50 +66,91 @@ public Mono> listAll() { var listOptions = ListOptions.builder() .andQuery(ExtensionUtil.notDeleting()) .build(); - return client.listAll(AuthProvider.class, listOptions, ExtensionUtil.defaultSort()) - .map(this::convertTo) - .collectList() - .flatMap(providers -> listMyConnections() - .map(connection -> connection.getSpec().getRegistrationId()) + var allProvidersMono = + client.listAll(AuthProvider.class, listOptions, ExtensionUtil.defaultSort()) + .map(this::convertTo) .collectList() - .map(connectedNames -> providers.stream() - .peek(provider -> { - boolean isBound = connectedNames.contains(provider.getName()); - provider.setIsBound(isBound); + .subscribeOn(Schedulers.boundedElastic()); + + var boundProvidersMono = listMyConnections() + .map(connection -> connection.getSpec().getRegistrationId()) + .collect(Collectors.toSet()) + .subscribeOn(Schedulers.boundedElastic()); + + return Mono.zip(allProvidersMono, boundProvidersMono, fetchProviderStates()) + .map(tuple3 -> { + var allProviders = tuple3.getT1(); + var boundProviderNames = tuple3.getT2(); + var stateMap = tuple3.getT3().stream() + .collect(Collectors.toMap(SystemSetting.AuthProviderState::getName, + Function.identity())); + return allProviders.stream() + .peek(authProvider -> { + authProvider.setIsBound( + boundProviderNames.contains(authProvider.getName())); + authProvider.setEnabled(false); + // set enabled state and priority + var state = stateMap.get(authProvider.getName()); + if (state != null) { + authProvider.setEnabled(state.isEnabled()); + authProvider.setPriority(state.getPriority()); + } }) - .collect(Collectors.toList()) - ) - .defaultIfEmpty(providers) - ) - .flatMap(providers -> fetchEnabledAuthProviders() - .map(names -> providers.stream() - .peek(provider -> { - boolean enabled = names.contains(provider.getName()); - provider.setEnabled(enabled); - }) - .collect(Collectors.toList()) - ) - .defaultIfEmpty(providers) - ); + .sorted(Comparator.comparingInt(ListedAuthProvider::getPriority) + .thenComparing(ListedAuthProvider::getName)) + .toList(); + }); } @Override public Flux getEnabledProviders() { - return fetchEnabledAuthProviders().flatMapMany(enabledNames -> { + return fetchProviderStates().flatMapMany(states -> { + var namePriorityMap = states.stream() + // filter enabled providers + .filter(SystemSetting.AuthProviderState::isEnabled) + .collect(Collectors.toMap(SystemSetting.AuthProviderState::getName, + SystemSetting.AuthProviderState::getPriority)); + var listOptions = ListOptions.builder() - .andQuery(QueryFactory.in("metadata.name", enabledNames)) + .andQuery(QueryFactory.in("metadata.name", namePriorityMap.keySet())) .andQuery(ExtensionUtil.notDeleting()) .build(); - return client.listAll(AuthProvider.class, listOptions, ExtensionUtil.defaultSort()); + return client.listAll(AuthProvider.class, listOptions, ExtensionUtil.defaultSort()) + .map(provider -> new AuthProviderWithPriority() + .setAuthProvider(provider) + .setPriority(namePriorityMap.getOrDefault( + provider.getMetadata().getName(), 0) + ) + ) + .sort(AuthProviderWithPriority::compareTo) + .map(AuthProviderWithPriority::getAuthProvider); }); } - private Mono> fetchEnabledAuthProviders() { - return client.fetch(ConfigMap.class, SystemSetting.SYSTEM_CONFIG) - .map(configMap -> { - SystemSetting.AuthProvider authProvider = getAuthProvider(configMap); - return authProvider.getEnabled(); - }); + @Data + @Accessors(chain = true) + static class AuthProviderWithPriority implements Comparable { + private AuthProvider authProvider; + private int priority; + + public String getName() { + return authProvider.getMetadata().getName(); + } + + @Override + public int compareTo(@NonNull AuthProviderWithPriority o) { + return Comparator.comparingInt(AuthProviderWithPriority::getPriority) + .thenComparing(AuthProviderWithPriority::getName) + .compare(this, o); + } + } + + private Mono> fetchProviderStates() { + return fetchSystemConfigMap() + .map(AuthProviderServiceImpl::getAuthProviderConfig) + .map(SystemSetting.AuthProvider::getStates) + .defaultIfEmpty(List.of()) + .subscribeOn(Schedulers.boundedElastic()); } Flux listMyConnections() { @@ -121,32 +166,6 @@ Flux listMyConnections() { }); } - private static Comparator defaultComparator() { - return Comparator.comparing((AuthProvider item) -> item.getSpec().getPriority()) - .thenComparing(item -> item.getMetadata().getName()) - .thenComparing(item -> item.getMetadata().getCreationTimestamp()); - } - - private Mono updateAuthProviderEnabled(Consumer> 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()); - - final Map data = configMap.getData(); - data.put(SystemSetting.AuthProvider.GROUP, - JsonUtils.objectToJson(authProvider)); - return client.update(configMap); - }); - } - private ListedAuthProvider convertTo(AuthProvider authProvider) { return ListedAuthProvider.builder() .name(authProvider.getMetadata().getName()) @@ -159,6 +178,7 @@ private ListedAuthProvider convertTo(AuthProvider authProvider) { .bindingUrl(authProvider.getSpec().getBindingUrl()) .unbindingUrl(authProvider.getSpec().getUnbindUrl()) .supportsBinding(supportsBinding(authProvider)) + .authType(authProvider.getSpec().getAuthType()) .isBound(false) .enabled(false) .privileged(privileged(authProvider)) @@ -176,7 +196,7 @@ private boolean privileged(AuthProvider authProvider) { } @NonNull - private static SystemSetting.AuthProvider getAuthProvider(ConfigMap configMap) { + private static SystemSetting.AuthProvider getAuthProviderConfig(ConfigMap configMap) { if (configMap.getData() == null) { configMap.setData(new HashMap<>()); } @@ -190,10 +210,41 @@ private static SystemSetting.AuthProvider getAuthProvider(ConfigMap configMap) { authProvider = JsonUtils.jsonToObject(providerGroup, SystemSetting.AuthProvider.class); } - - if (authProvider.getEnabled() == null) { - authProvider.setEnabled(new HashSet<>()); + if (authProvider.getStates() == null) { + authProvider.setStates(new ArrayList<>()); } + return authProvider; } + + private Mono updateAuthProviderEnabled(String name, boolean enabled) { + return Mono.defer(() -> fetchSystemConfigMap() + .flatMap(configMap -> { + var providerConfig = getAuthProviderConfig(configMap); + var stateToFoundOpt = providerConfig.getStates() + .stream() + .filter(state -> state.getName().equals(name)) + .findFirst(); + if (stateToFoundOpt.isEmpty()) { + var state = new SystemSetting.AuthProviderState() + .setName(name) + .setEnabled(enabled); + providerConfig.getStates().add(state); + } else { + stateToFoundOpt.get().setEnabled(enabled); + } + + configMap.getData().put(SystemSetting.AuthProvider.GROUP, + JsonUtils.objectToJson(providerConfig)); + + return client.update(configMap); + }) + ) + .retryWhen(Retry.backoff(5, Duration.ofMillis(100)) + .filter(OptimisticLockingFailureException.class::isInstance)); + } + + Mono fetchSystemConfigMap() { + return client.fetch(ConfigMap.class, SystemSetting.SYSTEM_CONFIG); + } } 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 e0484ff576..7fdd1258f7 100644 --- a/application/src/main/java/run/halo/app/security/ListedAuthProvider.java +++ b/application/src/main/java/run/halo/app/security/ListedAuthProvider.java @@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; +import run.halo.app.core.extension.AuthProvider; /** * A listed value object for {@link run.halo.app.core.extension.AuthProvider}. @@ -35,11 +36,15 @@ public class ListedAuthProvider { String unbindingUrl; + AuthProvider.AuthType authType; + Boolean isBound; Boolean enabled; + int priority; + Boolean supportsBinding; - + Boolean privileged; } diff --git a/application/src/main/java/run/halo/app/security/preauth/PreAuthLoginEndpoint.java b/application/src/main/java/run/halo/app/security/preauth/PreAuthLoginEndpoint.java index 641267d495..4905ae2c2b 100644 --- a/application/src/main/java/run/halo/app/security/preauth/PreAuthLoginEndpoint.java +++ b/application/src/main/java/run/halo/app/security/preauth/PreAuthLoginEndpoint.java @@ -61,14 +61,21 @@ RouterFunction preAuthLoginEndpoints() { var publicKey = cryptoService.readPublicKey() .map(key -> Base64.getEncoder().encodeToString(key)); var globalInfo = globalInfoService.getGlobalInfo().cache(); - var loginMethod = request.queryParam("method").orElse("local"); var authProviders = authProviderService.getEnabledProviders().cache(); - var authProvider = authProviders - .filter(ap -> Objects.equals(loginMethod, ap.getMetadata().getName())) - .next() - .switchIfEmpty(Mono.error(() -> new ServerWebInputException( - "Invalid login method " + loginMethod) - )) + + var allFormProviders = authProviders + .filter(ap -> AuthProvider.AuthType.FORM.equals(ap.getSpec().getAuthType())) + .cache(); + + var authProvider = Mono.justOrEmpty(request.queryParam("method")) + .flatMap(method -> allFormProviders + .filter(ap -> Objects.equals(method, ap.getMetadata().getName())) + .next() + .switchIfEmpty(Mono.error( + () -> new ServerWebInputException("Invalid login method " + method)) + ) + ) + .switchIfEmpty(allFormProviders.next()) .cache(); var fragmentTemplateName = authProvider.map(ap -> { @@ -83,9 +90,12 @@ RouterFunction preAuthLoginEndpoints() { var socialAuthProviders = authProviders .filter(ap -> !AuthProvider.AuthType.FORM.equals(ap.getSpec().getAuthType())) .cache(); - var formAuthProviders = authProviders - .filter(ap -> AuthProvider.AuthType.FORM.equals(ap.getSpec().getAuthType())) - .filter(ap -> !Objects.equals(loginMethod, ap.getMetadata().getName())) + var formAuthProviders = allFormProviders + .filterWhen(ap -> authProvider + .map(provider -> !Objects.equals(provider.getMetadata().getName(), + ap.getMetadata().getName()) + ) + ) .cache(); return serverRequestCache.saveRequest(exchange).then(Mono.defer(() -> 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 3c25919ed7..a0bbd463ad 100644 --- a/application/src/test/java/run/halo/app/security/AuthProviderServiceImplTest.java +++ b/application/src/test/java/run/halo/app/security/AuthProviderServiceImplTest.java @@ -9,7 +9,6 @@ import static org.mockito.Mockito.when; import java.util.HashMap; -import java.util.Set; import org.json.JSONException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -48,7 +47,7 @@ class AuthProviderServiceImplTest { AuthProviderServiceImpl authProviderService; @Test - void testEnable() { + void testEnable() throws JSONException { // Create a test auth provider AuthProvider authProvider = createAuthProvider("github"); when(client.get(eq(AuthProvider.class), eq("github"))).thenReturn(Mono.just(authProvider)); @@ -56,10 +55,7 @@ void testEnable() { ArgumentCaptor captor = ArgumentCaptor.forClass(ConfigMap.class); when(client.update(captor.capture())).thenReturn(Mono.empty()); - ConfigMap configMap = new ConfigMap(); - configMap.setData(new HashMap<>()); - when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG))) - .thenReturn(Mono.just(configMap)); + pileSystemConfigMap(); // Call the method being tested authProviderService.enable("github") @@ -68,51 +64,59 @@ void testEnable() { .verifyComplete(); ConfigMap value = captor.getValue(); - String providerSettingStr = value.getData().get(SystemSetting.AuthProvider.GROUP); - Set enabled = - JsonUtils.jsonToObject(providerSettingStr, SystemSetting.AuthProvider.class) - .getEnabled(); - assertThat(enabled).containsExactly("github"); + JSONAssert.assertEquals(""" + { + "states": [ + { + "name": "github", + "enabled": true, + "priority": 0 + } + ] + } + """, + value.getData().get(SystemSetting.AuthProvider.GROUP), + true); // Verify the result verify(client).get(AuthProvider.class, "github"); - verify(client).fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG)); } @Test - void testDisable() { + void testDisable() throws JSONException { // Create a test auth provider 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()); - ConfigMap configMap = new ConfigMap(); - configMap.setData(new HashMap<>()); - configMap.getData().put(SystemSetting.AuthProvider.GROUP, "{\"enabled\":[\"github\"]}"); - when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG))) - .thenReturn(Mono.just(configMap)); + pileSystemConfigMap(); // Call the method being tested Mono result = authProviderService.disable("github"); assertEquals(authProvider, result.block()); ConfigMap value = captor.getValue(); - String providerSettingStr = value.getData().get(SystemSetting.AuthProvider.GROUP); - Set enabled = - JsonUtils.jsonToObject(providerSettingStr, SystemSetting.AuthProvider.class) - .getEnabled(); - assertThat(enabled).isEmpty(); + JSONAssert.assertEquals(""" + { + "states": [ + { + "name": "github", + "enabled": false, + "priority": 0 + } + ] + } + """, + value.getData().get(SystemSetting.AuthProvider.GROUP), + true); // Verify the result verify(client).get(AuthProvider.class, "github"); - verify(client).fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG)); } - @Test @WithMockUser(username = "admin") void listAll() { @@ -129,11 +133,7 @@ void listAll() { when(client.listAll(same(UserConnection.class), any(ListOptions.class), any(Sort.class))) .thenReturn(Flux.empty()); - ConfigMap configMap = new ConfigMap(); - configMap.setData(new HashMap<>()); - configMap.getData().put(SystemSetting.AuthProvider.GROUP, "{\"enabled\":[\"github\"]}"); - when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG))) - .thenReturn(Mono.just(configMap)); + pileSystemConfigMap(); authProviderService.listAll() .as(StepVerifier::create) @@ -142,29 +142,36 @@ void listAll() { try { JSONAssert.assertEquals(""" [{ - "name": "github", - "displayName": "github", - "bindingUrl": "fake-binding-url", - "enabled": true, - "isBound": false, - "supportsBinding": false, - "privileged": false - }, { - "name": "gitlab", - "displayName": "gitlab", - "bindingUrl": "fake-binding-url", - "enabled": false, - "isBound": false, - "supportsBinding": false, - "privileged": false - },{ - - "name": "gitee", - "displayName": "gitee", - "enabled": false, - "isBound": false, - "supportsBinding": false, - "privileged": false + "name": "gitee", + "displayName": "gitee", + "authType": "OAUTH2", + "isBound": false, + "enabled": false, + "priority": 0, + "supportsBinding": false, + "privileged": false + }, + { + "name": "github", + "displayName": "github", + "bindingUrl": "fake-binding-url", + "authType": "OAUTH2", + "isBound": false, + "enabled": false, + "priority": 0, + "supportsBinding": false, + "privileged": false + }, + { + "name": "gitlab", + "displayName": "gitlab", + "bindingUrl": "fake-binding-url", + "authType": "OAUTH2", + "isBound": false, + "enabled": false, + "priority": 0, + "supportsBinding": false, + "privileged": false }] """, JsonUtils.objectToJson(result), @@ -183,6 +190,14 @@ AuthProvider createAuthProvider(String name) { authProvider.getMetadata().setLabels(new HashMap<>()); authProvider.setSpec(new AuthProvider.AuthProviderSpec()); authProvider.getSpec().setDisplayName(name); + authProvider.getSpec().setAuthType(AuthProvider.AuthType.OAUTH2); return authProvider; } + + void pileSystemConfigMap() { + ConfigMap configMap = new ConfigMap(); + configMap.setData(new HashMap<>()); + when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG))) + .thenReturn(Mono.just(configMap)); + } } \ No newline at end of file diff --git a/ui/console-src/modules/system/auth-providers/AuthProviders.vue b/ui/console-src/modules/system/auth-providers/AuthProviders.vue index 416ba857e5..050f805157 100644 --- a/ui/console-src/modules/system/auth-providers/AuthProviders.vue +++ b/ui/console-src/modules/system/auth-providers/AuthProviders.vue @@ -1,19 +1,22 @@ + diff --git a/ui/console-src/modules/system/auth-providers/module.ts b/ui/console-src/modules/system/auth-providers/module.ts index a2cb8d910c..80205ac469 100644 --- a/ui/console-src/modules/system/auth-providers/module.ts +++ b/ui/console-src/modules/system/auth-providers/module.ts @@ -16,6 +16,7 @@ export default definePlugin({ meta: { title: "core.identity_authentication.title", searchable: true, + permissions: ["*"], }, }, { @@ -24,6 +25,7 @@ export default definePlugin({ component: AuthProviderDetail, meta: { title: "core.identity_authentication.detail.title", + permissions: ["*"], }, }, ], diff --git a/ui/console-src/modules/system/users/UserList.vue b/ui/console-src/modules/system/users/UserList.vue index e438fc298d..788234a3b6 100644 --- a/ui/console-src/modules/system/users/UserList.vue +++ b/ui/console-src/modules/system/users/UserList.vue @@ -292,12 +292,14 @@ function onGrantPermissionModalClose() { {{ $t("core.user.actions.roles") }} - - - {{ $t("core.user.actions.identity_authentication") }} - + + + + {{ $t("core.user.actions.identity_authentication") }} + +