mirror of https://github.com/alibaba/nacos.git
V3.0 develop console mode (#13134)
* Use Page to replace List result for some maintainer api. * Support namespace page. * uniform Namespace model to api。 * Support console get server state from nacos-server * Fix update namespace invalid problem. * console support setting admin password. * Add Console maintainer client auth plugin to support identity request. * Support Nacos Console get users info from nacos server. * Support Nacos Console get role and permission info from nacos server. * Fix NPE by AuthConfig loading Circular Dependencies.
This commit is contained in:
parent
f127fea599
commit
2c025e20ec
|
@ -190,6 +190,9 @@ nacos.console.port=8080
|
|||
### Nacos Server Web context path:
|
||||
nacos.console.contextPath=
|
||||
|
||||
### Nacos Server context path, which link to nacos server `nacos.server.contextPath`, works when deployment type is `console`
|
||||
nacos.console.remote.server.context-path=/nacos
|
||||
|
||||
#************** Console UI Configuration ***************#
|
||||
|
||||
### Turn on/off the nacos console ui.
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.config.server.constant.PropertiesConstant;
|
||||
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
|
||||
import com.alibaba.nacos.core.namespace.injector.AbstractNamespaceDetailInjector;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ package com.alibaba.nacos.config.server.service;
|
|||
import com.alibaba.nacos.config.server.constant.PropertiesConstant;
|
||||
import com.alibaba.nacos.config.server.model.capacity.TenantCapacity;
|
||||
import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
|
@ -94,6 +94,7 @@ class EditorNameSpace extends React.Component {
|
|||
handleSubmit() {
|
||||
const { locale = {} } = this.props;
|
||||
this.field.validate((errors, values) => {
|
||||
console.log(values);
|
||||
if (errors) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,10 @@ request.middleWare((_config = {}) => {
|
|||
let config = _config;
|
||||
let { url = '' } = config;
|
||||
|
||||
const namespace = localStorage.getItem('namespace') ? localStorage.getItem('namespace') : '';
|
||||
let namespace = config?.data?.namespaceId;
|
||||
if (!namespace) {
|
||||
namespace = localStorage.getItem('namespace') ? localStorage.getItem('namespace') : '';
|
||||
}
|
||||
// 如果url中已经有 namespaceId, 不在data中添加namespaceId
|
||||
config.data =
|
||||
url.indexOf('namespaceId=') === -1
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* Nacos console starter.
|
||||
|
@ -28,6 +29,7 @@ import org.springframework.context.annotation.PropertySource;
|
|||
*/
|
||||
@SpringBootApplication(exclude = LdapAutoConfiguration.class)
|
||||
@PropertySource("classpath:nacos-console.properties")
|
||||
@EnableScheduling
|
||||
public class NacosConsole {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -19,11 +19,6 @@ package com.alibaba.nacos.console.config;
|
|||
import com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;
|
||||
import com.alibaba.nacos.core.code.ControllerMethodsCache;
|
||||
import com.alibaba.nacos.naming.selector.SelectorManager;
|
||||
import com.alibaba.nacos.plugin.auth.api.Permission;
|
||||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
@ -45,44 +40,4 @@ public class ConsoleDeploymentConfig {
|
|||
public SelectorManager selectorManager() {
|
||||
return new SelectorManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IAuthenticationManager authenticationManager() {
|
||||
// TODO implement remote authentication manager.
|
||||
return new IAuthenticationManager() {
|
||||
@Override
|
||||
public NacosUser authenticate(String username, String rawPassword) throws AccessException {
|
||||
return new NacosUser("nacos");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NacosUser authenticate(String jwtToken) throws AccessException {
|
||||
return new NacosUser("nacos");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NacosUser authenticate(HttpServletRequest httpServletRequest) throws AccessException {
|
||||
return new NacosUser("nacos");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authorize(Permission permission, NacosUser nacosUser) throws AccessException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGlobalAdminRole(String username) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGlobalAdminRole() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGlobalAdminRole(NacosUser nacosUser) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.alibaba.nacos.console.config;
|
||||
|
||||
import com.alibaba.nacos.auth.config.NacosAuthConfig;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.config.AbstractDynamicConfig;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ApiType;
|
||||
import com.alibaba.nacos.plugin.auth.constant.Constants;
|
||||
|
@ -41,6 +42,10 @@ public class NacosConsoleAuthConfig extends AbstractDynamicConfig implements Nac
|
|||
*/
|
||||
private String nacosAuthSystemType;
|
||||
|
||||
private String serverIdentityKey;
|
||||
|
||||
private String serverIdentityValue;
|
||||
|
||||
public NacosConsoleAuthConfig() {
|
||||
super("NacosConsoleAuth");
|
||||
resetConfig();
|
||||
|
@ -63,23 +68,25 @@ public class NacosConsoleAuthConfig extends AbstractDynamicConfig implements Nac
|
|||
|
||||
@Override
|
||||
public boolean isSupportServerIdentity() {
|
||||
return false;
|
||||
return StringUtils.isNotBlank(serverIdentityKey) && StringUtils.isNotBlank(serverIdentityValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerIdentityKey() {
|
||||
return "";
|
||||
return serverIdentityKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerIdentityValue() {
|
||||
return "";
|
||||
return serverIdentityValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getConfigFromEnv() {
|
||||
authEnabled = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_CONSOLE_ENABLED, Boolean.class, true);
|
||||
nacosAuthSystemType = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SYSTEM_TYPE, "");
|
||||
serverIdentityKey = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_KEY, "");
|
||||
serverIdentityValue = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_VALUE, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,41 +17,41 @@
|
|||
package com.alibaba.nacos.console.config;
|
||||
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;
|
||||
import com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.controller.v3.PermissionControllerV3;
|
||||
import com.alibaba.nacos.plugin.auth.impl.controller.v3.RoleControllerV3;
|
||||
import com.alibaba.nacos.plugin.auth.impl.controller.v3.UserControllerV3;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Configuration of console auth controller.
|
||||
* TODO use {@link Import} to dynamic load auth plugin controller like Mybatis.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@Configuration
|
||||
@EnabledInnerHandler
|
||||
public class NacosConsoleAuthControllerConfig {
|
||||
|
||||
@Bean
|
||||
public UserControllerV3 consoleUserControllerV3(NacosUserDetailsServiceImpl userDetailsService,
|
||||
NacosRoleServiceImpl roleService, AuthConfigs authConfigs, IAuthenticationManager iAuthenticationManager,
|
||||
public UserControllerV3 consoleUserControllerV3(NacosUserService userDetailsService, NacosRoleService roleService,
|
||||
AuthConfigs authConfigs, IAuthenticationManager iAuthenticationManager,
|
||||
TokenManagerDelegate jwtTokenManager) {
|
||||
return new UserControllerV3(userDetailsService, roleService, authConfigs, iAuthenticationManager,
|
||||
jwtTokenManager);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RoleControllerV3 consoleRoleControllerV3(NacosRoleServiceImpl roleService) {
|
||||
public RoleControllerV3 consoleRoleControllerV3(NacosRoleService roleService) {
|
||||
return new RoleControllerV3(roleService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PermissionControllerV3 permissionControllerV3(NacosRoleServiceImpl roleService) {
|
||||
public PermissionControllerV3 permissionControllerV3(NacosRoleService roleService) {
|
||||
return new PermissionControllerV3(roleService);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.console.config;
|
||||
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;
|
||||
import com.alibaba.nacos.core.code.ControllerMethodsCache;
|
||||
import com.alibaba.nacos.plugin.auth.impl.authenticate.DefaultAuthenticationManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceRemoteImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.impl.CachedJwtTokenManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.impl.JwtTokenManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserServiceRemoteImpl;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* Configuration of console auth service.
|
||||
* TODO use {@link Import} to dynamic load auth plugin controller like Mybatis.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@EnabledRemoteHandler
|
||||
@Import(AuthConfigs.class)
|
||||
@Configuration
|
||||
public class NacosConsoleAuthServiceConfig {
|
||||
|
||||
private final ControllerMethodsCache methodsCache;
|
||||
|
||||
public NacosConsoleAuthServiceConfig(ControllerMethodsCache methodsCache) {
|
||||
this.methodsCache = methodsCache;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void registerAuthPathToCache() {
|
||||
methodsCache.initClassMethod("com.alibaba.nacos.plugin.auth.impl.controller");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosRoleService nacosRoleService(AuthConfigs authConfigs) {
|
||||
return new NacosRoleServiceRemoteImpl(authConfigs);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosUserService nacosUserService(AuthConfigs authConfigs) {
|
||||
return new NacosUserServiceRemoteImpl(authConfigs);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public IAuthenticationManager defaultAuthenticationManager(NacosUserService userDetailsService,
|
||||
TokenManagerDelegate jwtTokenManager, NacosRoleService roleService) {
|
||||
return new DefaultAuthenticationManager(userDetailsService, jwtTokenManager, roleService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = TokenManagerDelegate.NACOS_AUTH_TOKEN_CACHING_ENABLED, havingValue = "false", matchIfMissing = true)
|
||||
public TokenManager tokenManager(AuthConfigs authConfigs) {
|
||||
return new JwtTokenManager(authConfigs);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = TokenManagerDelegate.NACOS_AUTH_TOKEN_CACHING_ENABLED, havingValue = "true")
|
||||
public TokenManager cachedTokenManager(AuthConfigs authConfigs) {
|
||||
return new CachedJwtTokenManager(new JwtTokenManager(authConfigs));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TokenManagerDelegate tokenManagerDelegate(TokenManager tokenManager) {
|
||||
return new TokenManagerDelegate(tokenManager);
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ import com.alibaba.nacos.common.utils.StringUtils;
|
|||
import com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;
|
||||
import com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;
|
||||
import com.alibaba.nacos.core.controller.compatibility.Compatibility;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
import com.alibaba.nacos.core.service.NamespaceOperationService;
|
||||
|
|
|
@ -18,13 +18,13 @@ package com.alibaba.nacos.console.controller;
|
|||
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;
|
||||
import com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;
|
||||
import com.alibaba.nacos.core.controller.compatibility.Compatibility;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
import com.alibaba.nacos.core.service.NacosServerStateService;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ApiType;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.alibaba.nacos.sys.module.ModuleState;
|
||||
import com.alibaba.nacos.sys.module.ModuleStateHolder;
|
||||
import com.alibaba.nacos.sys.utils.DiskUtils;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -33,7 +33,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.nacos.common.utils.StringUtils.FOLDER_SEPARATOR;
|
||||
|
@ -48,12 +47,19 @@ import static com.alibaba.nacos.common.utils.StringUtils.WINDOWS_FOLDER_SEPARATO
|
|||
@RestController
|
||||
@RequestMapping("/v1/console/server")
|
||||
@ExtractorManager.Extractor(httpExtractor = ConsoleDefaultHttpParamExtractor.class)
|
||||
@EnabledInnerHandler
|
||||
public class ServerStateController {
|
||||
|
||||
private static final String ANNOUNCEMENT_FILE = "announcement.conf";
|
||||
|
||||
private static final String GUIDE_FILE = "console-guide.conf";
|
||||
|
||||
private final NacosServerStateService stateService;
|
||||
|
||||
public ServerStateController(NacosServerStateService stateService) {
|
||||
this.stateService = stateService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server state of current server.
|
||||
*
|
||||
|
@ -62,11 +68,7 @@ public class ServerStateController {
|
|||
@GetMapping("/state")
|
||||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/console/server/state")
|
||||
public ResponseEntity<Map<String, String>> serverState() {
|
||||
Map<String, String> serverState = new HashMap<>(4);
|
||||
for (ModuleState each : ModuleStateHolder.getInstance().getAllModuleStates()) {
|
||||
each.getStates().forEach((s, o) -> serverState.put(s, null == o ? null : o.toString()));
|
||||
}
|
||||
return ResponseEntity.ok().body(serverState);
|
||||
return ResponseEntity.ok(stateService.getServerState());
|
||||
}
|
||||
|
||||
@GetMapping("/announcement")
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.console.controller.v2;
|
|||
import com.alibaba.nacos.api.annotation.NacosApi;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
|
@ -26,7 +27,6 @@ import com.alibaba.nacos.common.utils.StringUtils;
|
|||
import com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;
|
||||
import com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;
|
||||
import com.alibaba.nacos.core.controller.compatibility.Compatibility;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package com.alibaba.nacos.console.controller.v3;
|
||||
|
||||
import com.alibaba.nacos.api.annotation.NacosApi;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.api.model.v2.SupportedLanguage;
|
||||
import com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;
|
||||
|
@ -54,7 +55,7 @@ public class ConsoleServerStateController {
|
|||
* @return state json.
|
||||
*/
|
||||
@GetMapping("/state")
|
||||
public ResponseEntity<Map<String, String>> serverState() {
|
||||
public ResponseEntity<Map<String, String>> serverState() throws NacosException {
|
||||
Map<String, String> serverState = serverStateProxy.getServerState();
|
||||
return ResponseEntity.ok().body(serverState);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.alibaba.nacos.auth.annotation.Secured;
|
|||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;
|
||||
import com.alibaba.nacos.console.proxy.core.NamespaceProxy;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.CreateNamespaceForm;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
|
|
|
@ -20,12 +20,14 @@ package com.alibaba.nacos.console.controller.v3.naming;
|
|||
import com.alibaba.nacos.api.annotation.NacosApi;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.builder.InstanceBuilder;
|
||||
import com.alibaba.nacos.api.naming.utils.NamingUtils;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.console.proxy.naming.InstanceProxy;
|
||||
import com.alibaba.nacos.core.control.TpsControl;
|
||||
import com.alibaba.nacos.core.model.form.PageForm;
|
||||
|
@ -76,10 +78,13 @@ public class ConsoleInstanceController {
|
|||
@RequestMapping("/list")
|
||||
public Result<ObjectNode> getInstanceList(InstanceListForm instanceForm, PageForm pageForm) throws NacosException {
|
||||
instanceForm.validate();
|
||||
// TODO use Page + List<Instance> replace with console ui
|
||||
ObjectNode result = instanceProxy.listInstances(instanceForm.getNamespaceId(), instanceForm.getServiceName(),
|
||||
instanceForm.getGroupName(), instanceForm.getClusterName(), pageForm.getPageNo(),
|
||||
pageForm.getPageSize());
|
||||
Page<? extends Instance> instancePage = instanceProxy.listInstances(instanceForm.getNamespaceId(),
|
||||
instanceForm.getServiceName(), instanceForm.getGroupName(), instanceForm.getClusterName(),
|
||||
pageForm.getPageNo(), pageForm.getPageSize());
|
||||
// TODO use Page<? extends Instance> directly after console-ui modified
|
||||
ObjectNode result = JacksonUtils.createEmptyJsonNode();
|
||||
result.replace("instances", JacksonUtils.transferToJsonNode(instancePage.getPageItems()));
|
||||
result.put("count", instancePage.getTotalCount());
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package com.alibaba.nacos.console.handler;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
|
||||
/**
|
||||
|
@ -30,7 +31,8 @@ public interface HealthHandler {
|
|||
* Perform readiness check to determine if Nacos is ready to handle requests.
|
||||
*
|
||||
* @return readiness result
|
||||
* @throws NacosException if an error occurs during readiness check
|
||||
*/
|
||||
Result<String> checkReadiness();
|
||||
Result<String> checkReadiness() throws NacosException;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package com.alibaba.nacos.console.handler;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -30,8 +32,9 @@ public interface ServerStateHandler {
|
|||
* Get the current state of the server.
|
||||
*
|
||||
* @return a map containing the server state
|
||||
* @throws NacosException if an error occurs while retrieving the server state
|
||||
*/
|
||||
Map<String, String> getServerState();
|
||||
Map<String, String> getServerState() throws NacosException;
|
||||
|
||||
/**
|
||||
* Get the announcement content based on the language.
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
package com.alibaba.nacos.console.handler.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
package com.alibaba.nacos.console.handler.impl.inner;
|
||||
|
||||
import com.alibaba.nacos.console.handler.impl.AbstractServerStateHandler;
|
||||
import com.alibaba.nacos.sys.module.ModuleState;
|
||||
import com.alibaba.nacos.sys.module.ModuleStateHolder;
|
||||
import com.alibaba.nacos.core.service.NacosServerStateService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -33,12 +31,14 @@ import java.util.Map;
|
|||
@EnabledInnerHandler
|
||||
public class ServerStateInnerHandler extends AbstractServerStateHandler {
|
||||
|
||||
public Map<String, String> getServerState() {
|
||||
Map<String, String> serverState = new HashMap<>(4);
|
||||
for (ModuleState each : ModuleStateHolder.getInstance().getAllModuleStates()) {
|
||||
each.getStates().forEach((s, o) -> serverState.put(s, null == o ? null : o.toString()));
|
||||
private final NacosServerStateService stateService;
|
||||
|
||||
public ServerStateInnerHandler(NacosServerStateService stateService) {
|
||||
this.stateService = stateService;
|
||||
}
|
||||
return serverState;
|
||||
|
||||
public Map<String, String> getServerState() {
|
||||
return stateService.getServerState();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import com.alibaba.nacos.api.exception.api.NacosApiException;
|
|||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.console.handler.core.NamespaceHandler;
|
||||
import com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
import com.alibaba.nacos.core.service.NamespaceOperationService;
|
||||
|
|
|
@ -17,18 +17,18 @@
|
|||
package com.alibaba.nacos.console.handler.impl.inner.naming;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.utils.NamingUtils;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.trace.event.naming.UpdateInstanceTraceEvent;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;
|
||||
import com.alibaba.nacos.console.handler.naming.InstanceHandler;
|
||||
import com.alibaba.nacos.core.utils.PageUtil;
|
||||
import com.alibaba.nacos.naming.core.CatalogService;
|
||||
import com.alibaba.nacos.naming.core.CatalogServiceV2Impl;
|
||||
import com.alibaba.nacos.naming.core.InstanceOperatorClientImpl;
|
||||
import com.alibaba.nacos.naming.model.form.InstanceForm;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -42,7 +42,7 @@ import java.util.List;
|
|||
@EnabledInnerHandler
|
||||
public class InstanceInnerHandler implements InstanceHandler {
|
||||
|
||||
private final CatalogServiceV2Impl catalogServiceV2;
|
||||
private final CatalogService catalogService;
|
||||
|
||||
private final InstanceOperatorClientImpl instanceServiceV2;
|
||||
|
||||
|
@ -52,20 +52,16 @@ public class InstanceInnerHandler implements InstanceHandler {
|
|||
* @param catalogServiceV2 the service for catalog-related operations
|
||||
*/
|
||||
public InstanceInnerHandler(CatalogServiceV2Impl catalogServiceV2, InstanceOperatorClientImpl instanceServiceV2) {
|
||||
this.catalogServiceV2 = catalogServiceV2;
|
||||
this.catalogService = catalogServiceV2;
|
||||
this.instanceServiceV2 = instanceServiceV2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectNode listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName, String clusterName, int page,
|
||||
int pageSize) throws NacosException {
|
||||
List<? extends Instance> instances = catalogServiceV2.listInstances(namespaceId, groupName,
|
||||
public Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,
|
||||
String clusterName, int page, int pageSize) throws NacosException {
|
||||
List<? extends Instance> instances = catalogService.listInstances(namespaceId, groupName,
|
||||
serviceNameWithoutGroup, clusterName);
|
||||
List<? extends Instance> resultInstances = PageUtil.subPageList(instances, page, pageSize);
|
||||
ObjectNode result = JacksonUtils.createEmptyJsonNode();
|
||||
result.replace("instances", JacksonUtils.transferToJsonNode(resultInstances));
|
||||
result.put("count", instances.size());
|
||||
return result;
|
||||
return PageUtil.subPage(instances, page, pageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.console.handler.impl.remote;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.auth.config.NacosAuthConfigHolder;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.console.config.NacosConsoleAuthConfig;
|
||||
import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;
|
||||
import com.alibaba.nacos.plugin.auth.api.RequestResource;
|
||||
import com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Client Auth Plugin implementation for console remote maintainer client.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class ConsoleMaintainerClientAuthPlugin extends AbstractClientAuthService {
|
||||
|
||||
private LoginIdentityContext identityContext = new LoginIdentityContext();
|
||||
|
||||
@Override
|
||||
public Boolean login(Properties properties) {
|
||||
NacosConsoleAuthConfig authConfig = (NacosConsoleAuthConfig) NacosAuthConfigHolder.getInstance()
|
||||
.getNacosAuthConfigByScope(NacosConsoleAuthConfig.NACOS_CONSOLE_AUTH_SCOPE);
|
||||
if (authConfig.isSupportServerIdentity()) {
|
||||
identityContext.setParameter(authConfig.getServerIdentityKey(), authConfig.getServerIdentityValue());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServerList(List<String> serverList) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNacosRestTemplate(NacosRestTemplate nacosRestTemplate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginIdentityContext getLoginIdentityContext(RequestResource resource) {
|
||||
return identityContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws NacosException {
|
||||
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.alibaba.nacos.console.handler.impl.remote;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.console.handler.HealthHandler;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -29,10 +30,16 @@ import org.springframework.stereotype.Service;
|
|||
@EnabledRemoteHandler
|
||||
public class HealthRemoteHandler implements HealthHandler {
|
||||
|
||||
private final NacosMaintainerClientHolder clientHolder;
|
||||
|
||||
public HealthRemoteHandler(NacosMaintainerClientHolder clientHolder) {
|
||||
this.clientHolder = clientHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> checkReadiness() {
|
||||
// TODO call nacos servers
|
||||
return Result.success("ok");
|
||||
public Result<String> checkReadiness() throws NacosException {
|
||||
Boolean result = clientHolder.getNamingMaintainerService().readiness();
|
||||
return result ? Result.success("ok") : Result.failure("Nacos server readiness failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ public class NacosMaintainerClientHolder {
|
|||
String memberAddressString = StringUtils.join(memberAddress, ",");
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, memberAddressString);
|
||||
// TODO Add admin user and pass
|
||||
namingMaintainerService = NamingMaintainerFactory.createNamingMaintainerService(properties);
|
||||
configMaintainerService = ConfigMaintainerFactory.createConfigMaintainerService(properties);
|
||||
// TODO sub member change event to upgrade maintainer client server members.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.alibaba.nacos.console.handler.impl.remote;
|
||||
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.console.handler.impl.AbstractServerStateHandler;
|
||||
import com.alibaba.nacos.sys.env.Constants;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
|
@ -24,7 +24,6 @@ import com.alibaba.nacos.sys.module.ModuleState;
|
|||
import com.alibaba.nacos.sys.module.ModuleStateHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -36,13 +35,14 @@ import java.util.Map;
|
|||
@EnabledRemoteHandler
|
||||
public class ServerStateRemoteHandler extends AbstractServerStateHandler {
|
||||
|
||||
public Map<String, String> getServerState() {
|
||||
Map<String, String> serverState = new HashMap<>(4);
|
||||
// TODO get state from nacos servers
|
||||
// Mock first
|
||||
serverState.put(Constants.STARTUP_MODE_STATE, EnvUtil.STANDALONE_MODE_ALONE);
|
||||
serverState.put(Constants.FUNCTION_MODE_STATE, EnvUtil.getFunctionMode());
|
||||
serverState.put(Constants.NACOS_VERSION, VersionUtils.version);
|
||||
private final NacosMaintainerClientHolder clientHolder;
|
||||
|
||||
public ServerStateRemoteHandler(NacosMaintainerClientHolder clientHolder) {
|
||||
this.clientHolder = clientHolder;
|
||||
}
|
||||
|
||||
public Map<String, String> getServerState() throws NacosException {
|
||||
Map<String, String> serverState = this.clientHolder.getNamingMaintainerService().getServerState();
|
||||
serverState.put(Constants.SERVER_PORT_STATE, EnvUtil.getProperty("nacos.console.port", "8080"));
|
||||
// Add current console states
|
||||
for (ModuleState each : ModuleStateHolder.getInstance().getAllModuleStates()) {
|
||||
|
|
|
@ -17,15 +17,13 @@
|
|||
package com.alibaba.nacos.console.handler.impl.remote.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.console.handler.core.NamespaceHandler;
|
||||
import com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;
|
||||
import com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -45,32 +43,12 @@ public class NamespaceRemoteHandler implements NamespaceHandler {
|
|||
|
||||
@Override
|
||||
public List<Namespace> getNamespaceList() throws NacosException {
|
||||
return transferToNamespaceList(clientHolder.getNamingMaintainerService().getNamespaceList());
|
||||
}
|
||||
|
||||
private List<Namespace> transferToNamespaceList(List<com.alibaba.nacos.api.model.response.Namespace> namespaceList) {
|
||||
if (null == namespaceList) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Namespace> result = new ArrayList<>();
|
||||
namespaceList.forEach(namespace -> result.add(transferToNamespace(namespace)));
|
||||
return result;
|
||||
return clientHolder.getNamingMaintainerService().getNamespaceList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Namespace getNamespaceDetail(String namespaceId) throws NacosException {
|
||||
return transferToNamespace(clientHolder.getNamingMaintainerService().getNamespace(namespaceId));
|
||||
}
|
||||
|
||||
private Namespace transferToNamespace(com.alibaba.nacos.api.model.response.Namespace namespace) {
|
||||
Namespace targetNamespace = new Namespace();
|
||||
targetNamespace.setNamespaceShowName(namespace.getNamespaceShowName());
|
||||
targetNamespace.setNamespaceDesc(namespace.getNamespaceDesc());
|
||||
targetNamespace.setNamespace(namespace.getNamespace());
|
||||
targetNamespace.setQuota(namespace.getQuota());
|
||||
targetNamespace.setConfigCount(namespace.getConfigCount());
|
||||
targetNamespace.setType(namespace.getType());
|
||||
return targetNamespace;
|
||||
return clientHolder.getNamingMaintainerService().getNamespace(namespaceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,8 +59,9 @@ public class NamespaceRemoteHandler implements NamespaceHandler {
|
|||
|
||||
@Override
|
||||
public Boolean updateNamespace(NamespaceForm namespaceForm) throws NacosException {
|
||||
return clientHolder.getNamingMaintainerService().updateNamespace(namespaceForm.getNamespaceId(),
|
||||
namespaceForm.getNamespaceName(), namespaceForm.getNamespaceDesc());
|
||||
return clientHolder.getNamingMaintainerService()
|
||||
.updateNamespace(namespaceForm.getNamespaceId(), namespaceForm.getNamespaceName(),
|
||||
namespaceForm.getNamespaceDesc());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,14 +17,13 @@
|
|||
package com.alibaba.nacos.console.handler.impl.remote.naming;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;
|
||||
import com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;
|
||||
import com.alibaba.nacos.console.handler.naming.InstanceHandler;
|
||||
import com.alibaba.nacos.core.utils.PageUtil;
|
||||
import com.alibaba.nacos.naming.model.form.InstanceForm;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -45,15 +44,11 @@ public class InstanceRemoteHandler implements InstanceHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ObjectNode listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,
|
||||
public Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,
|
||||
String clusterName, int page, int pageSize) throws NacosException {
|
||||
List<Instance> instances = clientHolder.getNamingMaintainerService()
|
||||
.listInstances(namespaceId, groupName, serviceNameWithoutGroup, clusterName, false);
|
||||
List<? extends Instance> resultInstances = PageUtil.subPageList(instances, page, pageSize);
|
||||
ObjectNode result = JacksonUtils.createEmptyJsonNode();
|
||||
result.replace("instances", JacksonUtils.transferToJsonNode(resultInstances));
|
||||
result.put("count", instances.size());
|
||||
return result;
|
||||
return PageUtil.subPage(instances, page, pageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
package com.alibaba.nacos.console.handler.naming;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.naming.model.form.InstanceForm;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
/**
|
||||
* Interface for handling instance-related operations.
|
||||
|
@ -38,10 +38,10 @@ public interface InstanceHandler {
|
|||
* @param clusterName the cluster name
|
||||
* @param page the page number
|
||||
* @param pageSize the size of the page
|
||||
* @return a JSON node containing the instances information
|
||||
* @return the page object of {@link Instance}
|
||||
* @throws NacosException if the list operation fails
|
||||
*/
|
||||
ObjectNode listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName, String clusterName,
|
||||
Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName, String clusterName,
|
||||
int page, int pageSize) throws NacosException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -96,7 +96,7 @@ public interface ServiceHandler {
|
|||
* @param serviceName the service name
|
||||
* @param groupName the group name
|
||||
* @param ignoreEmptyService whether to filter services with empty instances
|
||||
* @return if withInstances is {@code true}, return List of {@link ServiceDetailInfo}, otherwise return List of {@link ServiceView}
|
||||
* @return if withInstances is {@code true}, return Page of {@link ServiceDetailInfo}, otherwise return Page of {@link ServiceView}
|
||||
* @throws NacosException if an error occurs during fetching service details
|
||||
*/
|
||||
Object getServiceList(boolean withInstances, String namespaceId, int pageNo, int pageSize, String serviceName,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package com.alibaba.nacos.console.proxy;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.console.handler.HealthHandler;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -40,7 +41,7 @@ public class HealthProxy {
|
|||
*
|
||||
* @return readiness result
|
||||
*/
|
||||
public Result<String> checkReadiness() {
|
||||
public Result<String> checkReadiness() throws NacosException {
|
||||
return healthHandler.checkReadiness();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package com.alibaba.nacos.console.proxy;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.console.handler.ServerStateHandler;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -41,7 +42,7 @@ public class ServerStateProxy {
|
|||
*
|
||||
* @return the server state as a Map
|
||||
*/
|
||||
public Map<String, String> getServerState() {
|
||||
public Map<String, String> getServerState() throws NacosException {
|
||||
return serverStateHandler.getServerState();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ package com.alibaba.nacos.console.proxy.core;
|
|||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.console.handler.core.NamespaceHandler;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
package com.alibaba.nacos.console.proxy.naming;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.console.handler.naming.InstanceHandler;
|
||||
import com.alibaba.nacos.naming.model.form.InstanceForm;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
|
@ -52,11 +52,11 @@ public class InstanceProxy {
|
|||
* @param clusterName the cluster name
|
||||
* @param page the page number
|
||||
* @param pageSize the size of the page
|
||||
* @return a JSON node containing the instances information
|
||||
* @return the page object of {@link Instance}
|
||||
* @throws IllegalArgumentException if the deployment type is invalid
|
||||
* @throws NacosException if the list operation fails
|
||||
*/
|
||||
public ObjectNode listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,
|
||||
public Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,
|
||||
String clusterName, int page, int pageSize) throws NacosException {
|
||||
return instanceHandler.listInstances(namespaceId, serviceNameWithoutGroup, groupName, clusterName, page,
|
||||
pageSize);
|
||||
|
|
|
@ -128,15 +128,17 @@ public class ServiceProxy {
|
|||
public Object getServiceList(boolean withInstances, String namespaceId, int pageNo, int pageSize,
|
||||
String serviceName, String groupName, boolean hasIpCount) throws NacosException {
|
||||
if (withInstances) {
|
||||
return serviceHandler.getServiceList(withInstances, namespaceId, pageNo, pageSize, serviceName, groupName,
|
||||
hasIpCount);
|
||||
// TODO use result directly after console ui changed and return page object
|
||||
Page<ServiceDetailInfo> serviceDetailInfoPage = (Page<ServiceDetailInfo>) serviceHandler.getServiceList(
|
||||
withInstances, namespaceId, pageNo, pageSize, serviceName, groupName, hasIpCount);
|
||||
return serviceDetailInfoPage.getPageItems();
|
||||
}
|
||||
// TODO use result directly after console ui changed and return page object
|
||||
List<ServiceView> views = (List<ServiceView>) serviceHandler.getServiceList(withInstances, namespaceId, pageNo,
|
||||
Page<ServiceView> views = (Page<ServiceView>) serviceHandler.getServiceList(withInstances, namespaceId, pageNo,
|
||||
pageSize, serviceName, groupName, hasIpCount);
|
||||
ObjectNode result = JacksonUtils.createEmptyJsonNode();
|
||||
result.put(FieldsConstants.COUNT, views.size());
|
||||
result.set(FieldsConstants.SERVICE_LIST, JacksonUtils.transferToJsonNode(views));
|
||||
result.put(FieldsConstants.COUNT, views.getTotalCount());
|
||||
result.set(FieldsConstants.SERVICE_LIST, JacksonUtils.transferToJsonNode(views.getPageItems()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
# Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -13,8 +13,5 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
server.port=8848
|
||||
server.servlet.context-path=/nacos
|
||||
nacos.cmdb.dumpTaskInterval=3600
|
||||
nacos.cmdb.eventTaskInterval=10
|
||||
nacos.cmdb.loadDataAtStart=true
|
||||
|
||||
com.alibaba.nacos.console.handler.impl.remote.ConsoleMaintainerClientAuthPlugin
|
|
@ -1,253 +0,0 @@
|
|||
#
|
||||
# Copyright 1999-2024 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#*************** Spring Boot Related Configurations ***************#
|
||||
### Default web context path:
|
||||
server.servlet.contextPath=/nacos
|
||||
### Include message field
|
||||
server.error.include-message=ALWAYS
|
||||
### Default web server port:
|
||||
server.port=8848
|
||||
|
||||
#*************** Network Related Configurations ***************#
|
||||
### If prefer hostname over ip for Nacos server addresses in cluster.conf:
|
||||
# nacos.inetutils.prefer-hostname-over-ip=false
|
||||
|
||||
### Specify local server's IP:
|
||||
# nacos.inetutils.ip-address=
|
||||
|
||||
#*************** Config Module Related Configurations ***************#
|
||||
### Deprecated configuration property, it is recommended to use `spring.sql.init.platform` replaced.
|
||||
# spring.datasource.platform=mysql
|
||||
# nacos.plugin.datasource.log.enabled=true
|
||||
#spring.sql.init.platform=mysql
|
||||
### Count of DB:
|
||||
# db.num=1
|
||||
|
||||
### Connect URL of DB:
|
||||
#db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
|
||||
#db.user=nacos
|
||||
#db.password=nacos
|
||||
|
||||
### the maximum retry times for push
|
||||
nacos.config.push.maxRetryTime=50
|
||||
|
||||
#*************** Naming Module Related Configurations ***************#
|
||||
### Data dispatch task execution period in milliseconds:
|
||||
|
||||
### If enable data warmup. If set to false, the server would accept request without local data preparation:
|
||||
# nacos.naming.data.warmup=true
|
||||
|
||||
### If enable the instance auto expiration, kind like of health check of instance:
|
||||
# nacos.naming.expireInstance=true
|
||||
|
||||
nacos.naming.empty-service.auto-clean=true
|
||||
nacos.naming.empty-service.clean.initial-delay-ms=50000
|
||||
nacos.naming.empty-service.clean.period-time-ms=30000
|
||||
|
||||
|
||||
#*************** CMDB Module Related Configurations ***************#
|
||||
### The interval to dump external CMDB in seconds:
|
||||
# nacos.cmdb.dumpTaskInterval=3600
|
||||
|
||||
### The interval of polling data change event in seconds:
|
||||
# nacos.cmdb.eventTaskInterval=10
|
||||
|
||||
### The interval of loading labels in seconds:
|
||||
# nacos.cmdb.labelTaskInterval=300
|
||||
|
||||
### If turn on data loading task:
|
||||
# nacos.cmdb.loadDataAtStart=false
|
||||
|
||||
|
||||
#*************** Metrics Related Configurations ***************#
|
||||
### Metrics for prometheus
|
||||
#management.endpoints.web.exposure.include=*
|
||||
|
||||
### Metrics for elastic search
|
||||
management.elastic.metrics.export.enabled=false
|
||||
#management.elastic.metrics.export.host=http://localhost:9200
|
||||
|
||||
### Metrics for influx
|
||||
management.influx.metrics.export.enabled=false
|
||||
#management.influx.metrics.export.db=springboot
|
||||
#management.influx.metrics.export.influx.uri=http://localhost:8086
|
||||
#management.influx.metrics.export.influx.auto-create-db=true
|
||||
#management.influx.metrics.export.influx.consistency=one
|
||||
#management.influx.metrics.export.influx.compressed=true
|
||||
|
||||
#*************** Access Log Related Configurations ***************#
|
||||
### If turn on the access log:
|
||||
server.tomcat.accesslog.enabled=true
|
||||
|
||||
### accesslog automatic cleaning time
|
||||
server.tomcat.accesslog.max-days=30
|
||||
|
||||
### The access log pattern:
|
||||
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
|
||||
|
||||
### The directory of access log:
|
||||
server.tomcat.basedir=file:.
|
||||
|
||||
|
||||
#*************** Access Control Related Configurations ***************#
|
||||
### If enable spring security, this option is deprecated in 1.2.0:
|
||||
#spring.security.enabled=false
|
||||
### The ignore urls of auth, is deprecated in 1.2.0:
|
||||
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
|
||||
|
||||
### The auth system to use, currently only 'nacos' and 'ldap' is supported:
|
||||
nacos.core.auth.system.type=nacos
|
||||
|
||||
### If turn on auth system v3:
|
||||
nacos.core.auth.enabled=false
|
||||
nacos.core.auth.console.enabled=true
|
||||
|
||||
### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.
|
||||
nacos.core.auth.caching.enabled=true
|
||||
|
||||
### Since 1.4.1, Turn on/off white auth for user-agent: nacos-server, only for upgrade from old version.
|
||||
nacos.core.auth.enable.userAgentAuthWhite=false
|
||||
|
||||
### Since 1.4.1, worked when nacos.core.auth.enabled=true and nacos.core.auth.enable.userAgentAuthWhite=false.
|
||||
### The two properties is the white list for auth and used by identity the request from other server.
|
||||
nacos.core.auth.server.identity.key=
|
||||
nacos.core.auth.server.identity.value=
|
||||
|
||||
### worked when nacos.core.auth.system.type=nacos
|
||||
### The token expiration in seconds:
|
||||
nacos.core.auth.plugin.nacos.token.cache.enable=false
|
||||
nacos.core.auth.plugin.nacos.token.expire.seconds=18000
|
||||
### The default token (Base64 string):
|
||||
#nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
|
||||
nacos.core.auth.plugin.nacos.token.secret.key=
|
||||
|
||||
### worked when nacos.core.auth.system.type=ldap,{0} is Placeholder,replace login username
|
||||
#nacos.core.auth.ldap.url=ldap://localhost:389
|
||||
#nacos.core.auth.ldap.basedc=dc=example,dc=org
|
||||
#nacos.core.auth.ldap.userDn=cn=admin,${nacos.core.auth.ldap.basedc}
|
||||
#nacos.core.auth.ldap.password=admin
|
||||
#nacos.core.auth.ldap.userdn=cn={0},dc=example,dc=org
|
||||
#nacos.core.auth.ldap.filter.prefix=uid
|
||||
#nacos.core.auth.ldap.case.sensitive=true
|
||||
#nacos.core.auth.ldap.ignore.partial.result.exception=false
|
||||
|
||||
#*************** Control Plugin Related Configurations ***************#
|
||||
# plugin type
|
||||
#nacos.plugin.control.manager.type=nacos
|
||||
|
||||
# local control rule storage dir, default ${nacos.home}/data/connection and ${nacos.home}/data/tps
|
||||
#nacos.plugin.control.rule.local.basedir=${nacos.home}
|
||||
|
||||
# external control rule storage type, if exist
|
||||
#nacos.plugin.control.rule.external.storage=
|
||||
|
||||
#*************** Config Change Plugin Related Configurations ***************#
|
||||
# webhook
|
||||
#nacos.core.config.plugin.webhook.enabled=false
|
||||
# It is recommended to use EB https://help.aliyun.com/document_detail/413974.html
|
||||
#nacos.core.config.plugin.webhook.url=http://localhost:8080/webhook/send?token=***
|
||||
# The content push max capacity ,byte
|
||||
#nacos.core.config.plugin.webhook.contentMaxCapacity=102400
|
||||
|
||||
# whitelist
|
||||
#nacos.core.config.plugin.whitelist.enabled=false
|
||||
# The import file suffixs
|
||||
#nacos.core.config.plugin.whitelist.suffixs=xml,text,properties,yaml,html
|
||||
# fileformatcheck,which validate the import file of type and content
|
||||
#nacos.core.config.plugin.fileformatcheck.enabled=false
|
||||
|
||||
#*************** Istio Related Configurations ***************#
|
||||
### If turn on the MCP server:
|
||||
nacos.istio.mcp.server.enabled=false
|
||||
|
||||
###*************** Add from 1.3.0 ***************###
|
||||
|
||||
#*************** Core Related Configurations ***************#
|
||||
|
||||
### set the WorkerID manually
|
||||
# nacos.core.snowflake.worker-id=
|
||||
|
||||
### Member-MetaData
|
||||
# nacos.core.member.meta.site=
|
||||
# nacos.core.member.meta.adweight=
|
||||
# nacos.core.member.meta.weight=
|
||||
|
||||
### MemberLookup
|
||||
### Addressing pattern category, If set, the priority is highest
|
||||
# nacos.core.member.lookup.type=[file,address-server]
|
||||
## Set the cluster list with a configuration file or command-line argument
|
||||
# nacos.member.list=192.168.16.101:8847?raft_port=8807,192.168.16.101?raft_port=8808,192.168.16.101:8849?raft_port=8809
|
||||
## for AddressServerMemberLookup
|
||||
# Maximum number of retries to query the address server upon initialization
|
||||
# nacos.core.address-server.retry=5
|
||||
## Server domain name address of [address-server] mode
|
||||
# address.server.domain=jmenv.tbsite.net
|
||||
## Server port of [address-server] mode
|
||||
# address.server.port=8080
|
||||
## Request address of [address-server] mode
|
||||
# address.server.url=/nacos/serverlist
|
||||
|
||||
#*************** JRaft Related Configurations ***************#
|
||||
|
||||
### Sets the Raft cluster election timeout, default value is 5 second
|
||||
# nacos.core.protocol.raft.data.election_timeout_ms=5000
|
||||
### Sets the amount of time the Raft snapshot will execute periodically, default is 30 minute
|
||||
# nacos.core.protocol.raft.data.snapshot_interval_secs=30
|
||||
### raft internal worker threads
|
||||
# nacos.core.protocol.raft.data.core_thread_num=8
|
||||
### Number of threads required for raft business request processing
|
||||
# nacos.core.protocol.raft.data.cli_service_thread_num=4
|
||||
### raft linear read strategy. Safe linear reads are used by default, that is, the Leader tenure is confirmed by heartbeat
|
||||
# nacos.core.protocol.raft.data.read_index_type=ReadOnlySafe
|
||||
### rpc request timeout, default 5 seconds
|
||||
# nacos.core.protocol.raft.data.rpc_request_timeout_ms=5000
|
||||
### enable to support prometheus service discovery
|
||||
#nacos.prometheus.metrics.enabled=true
|
||||
|
||||
#************** Console UI Configuration ***************#
|
||||
|
||||
### Turn on/off the nacos console ui.
|
||||
#nacos.console.ui.enabled=true
|
||||
|
||||
###*************** Add from 3.0.0 ***************###
|
||||
|
||||
#*************** Deployment Type Configuration ***************#
|
||||
|
||||
### Sets the deployment type: 'merged' for joint deployment, 'server' for separate deployment server only, 'console' for separate deployment console only.
|
||||
nacos.deployment.type=merged
|
||||
|
||||
#************** Nacos Admin Compatibility Related Configurations ***************#
|
||||
|
||||
### Enabled for open API compatibility
|
||||
# nacos.core.api.compatibility.client.enabled=true
|
||||
### Enabled for admin API compatibility
|
||||
# nacos.core.api.compatibility.admin.enabled=true
|
||||
### Enabled for console API compatibility
|
||||
# nacos.core.api.compatibility.console.enabled=false
|
||||
|
||||
#*************** K8s Related Configurations ***************#
|
||||
### If turn on the K8s sync:
|
||||
nacos.k8s.sync.enabled=false
|
||||
|
||||
### If use the Java API from an application outside a kubernetes cluster
|
||||
#nacos.k8s.sync.outsideCluster=false
|
||||
#nacos.k8s.sync.kubeConfig=/.kube/config
|
||||
|
||||
#*************** DistributedLock Configurations ***************#
|
||||
|
||||
# nacos.lock.default_expire_time = 30000000
|
||||
# nacos.lock.max_expire_time = 1800000000
|
|
@ -35,7 +35,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="console-ui/public/css/icon.css">
|
||||
<link rel="stylesheet" type="text/css" href="console-ui/public/css/font-awesome.css">
|
||||
<!-- 第三方css结束 -->
|
||||
<link href="./css/main.css?e2df596fdcbaf967c31d" rel="stylesheet"></head>
|
||||
<link href="./css/main.css?66b305f37e2c8be3d620" rel="stylesheet"></head>
|
||||
|
||||
<body>
|
||||
<div id="root" style="overflow:hidden"></div>
|
||||
|
@ -56,6 +56,6 @@
|
|||
<script src="console-ui/public/js/merge.js"></script>
|
||||
<script src="console-ui/public/js/loader.js"></script>
|
||||
<!-- 第三方js结束 -->
|
||||
<script type="text/javascript" src="./js/main.js?e2df596fdcbaf967c31d"></script></body>
|
||||
<script type="text/javascript" src="./js/main.js?66b305f37e2c8be3d620"></script></body>
|
||||
|
||||
</html>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -18,7 +18,7 @@ package com.alibaba.nacos.console.controller;
|
|||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
import com.alibaba.nacos.core.service.NamespaceOperationService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
|
@ -18,32 +18,29 @@ package com.alibaba.nacos.console.controller;
|
|||
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||
import com.alibaba.nacos.core.service.NacosServerStateService;
|
||||
import com.alibaba.nacos.sys.env.Constants;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.alibaba.nacos.sys.module.ModuleState;
|
||||
import com.alibaba.nacos.sys.module.ModuleStateBuilder;
|
||||
import com.alibaba.nacos.sys.module.ModuleStateHolder;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* ServerStateController unit test.
|
||||
|
@ -58,50 +55,28 @@ class ServerStateControllerTest {
|
|||
|
||||
private static final String CONSOLE_URL = "/v1/console/server/state";
|
||||
|
||||
@Mock
|
||||
private NacosServerStateService stateService;
|
||||
|
||||
@InjectMocks
|
||||
private ServerStateController serverStateController;
|
||||
|
||||
private static List<ModuleStateBuilder> cachedBuilders;
|
||||
|
||||
private MockMvc mockmvc;
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@BeforeAll
|
||||
static void setUpBeforeAll() {
|
||||
cachedBuilders = (List<ModuleStateBuilder>) ReflectionTestUtils.getField(ModuleStateHolder.getInstance(),
|
||||
"moduleStateBuilders");
|
||||
List<ModuleStateBuilder> mockBuilders = new LinkedList<>();
|
||||
mockBuilders.add(new ModuleStateBuilder() {
|
||||
@Override
|
||||
public ModuleState build() {
|
||||
ModuleState moduleState = new ModuleState("mock");
|
||||
moduleState.newState(Constants.STARTUP_MODE_STATE, EnvUtil.STANDALONE_MODE_CLUSTER);
|
||||
moduleState.newState(Constants.FUNCTION_MODE_STATE, null);
|
||||
moduleState.newState(Constants.NACOS_VERSION, VersionUtils.version);
|
||||
return moduleState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCacheable() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
ReflectionTestUtils.setField(ModuleStateHolder.getInstance(), "moduleStateBuilders", mockBuilders);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
environment = new MockEnvironment();
|
||||
EnvUtil.setEnvironment(environment);
|
||||
Map<String, String> mock = new HashMap<>();
|
||||
mock.put(Constants.STARTUP_MODE_STATE, EnvUtil.STANDALONE_MODE_CLUSTER);
|
||||
mock.put(Constants.FUNCTION_MODE_STATE, null);
|
||||
mock.put(Constants.NACOS_VERSION, VersionUtils.version);
|
||||
when(stateService.getServerState()).thenReturn(mock);
|
||||
mockmvc = MockMvcBuilders.standaloneSetup(serverStateController).build();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDownAfterAll() {
|
||||
ReflectionTestUtils.setField(ModuleStateHolder.getInstance(), "moduleStateBuilders", cachedBuilders);
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverState() throws Exception {
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(CONSOLE_URL);
|
||||
|
|
|
@ -19,7 +19,7 @@ package com.alibaba.nacos.console.controller.v2;
|
|||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.NamespaceTypeEnum;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
|
|
|
@ -20,7 +20,7 @@ package com.alibaba.nacos.console.controller.v3.core;
|
|||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.console.proxy.core.NamespaceProxy;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package com.alibaba.nacos.console.controller.v3.naming;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
|
@ -25,7 +26,6 @@ import com.alibaba.nacos.naming.misc.SwitchDomain;
|
|||
import com.alibaba.nacos.naming.model.form.InstanceForm;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -45,8 +45,8 @@ import static org.mockito.ArgumentMatchers.any;
|
|||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* ConsoleInstanceControllerTest.
|
||||
|
@ -74,9 +74,9 @@ public class ConsoleInstanceControllerTest {
|
|||
|
||||
@Test
|
||||
void testGetInstanceList() throws Exception {
|
||||
ObjectNode instances = JsonNodeFactory.instance.objectNode();
|
||||
when(instanceProxy.listInstances(anyString(), anyString(), anyString(), anyString(), anyInt(),
|
||||
anyInt())).thenReturn(instances);
|
||||
Page<? extends Instance> page = new Page<>();
|
||||
doReturn(page).when(instanceProxy)
|
||||
.listInstances(anyString(), anyString(), anyString(), anyString(), anyInt(), anyInt());
|
||||
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/v3/console/ns/instance/list")
|
||||
.param("namespaceId", "default").param("serviceName", "testService").param("pageNo", "1")
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.alibaba.nacos.api.model.Page;
|
|||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ServiceView;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.SubscriberInfo;
|
||||
import com.alibaba.nacos.console.proxy.naming.ServiceProxy;
|
||||
import com.alibaba.nacos.core.model.form.AggregationForm;
|
||||
|
@ -202,8 +203,11 @@ public class ConsoleServiceControllerTest {
|
|||
|
||||
@Test
|
||||
void testGetServiceList() throws Exception {
|
||||
Page<ServiceView> expected = new Page<>();
|
||||
expected.setTotalCount(1);
|
||||
expected.getPageItems().add(new ServiceView());
|
||||
when(serviceProxy.getServiceList(anyBoolean(), anyString(), anyInt(), anyInt(), anyString(), anyString(),
|
||||
anyBoolean())).thenReturn(Collections.singletonList(new Object()));
|
||||
anyBoolean())).thenReturn(expected);
|
||||
PageForm pageForm = new PageForm();
|
||||
pageForm.setPageNo(1);
|
||||
pageForm.setPageSize(10);
|
||||
|
@ -217,8 +221,8 @@ public class ConsoleServiceControllerTest {
|
|||
anyBoolean());
|
||||
|
||||
assertEquals(ErrorCode.SUCCESS.getCode(), actual.getCode());
|
||||
assertInstanceOf(List.class, actual.getData());
|
||||
assertEquals(1, ((List<?>) actual.getData()).size());
|
||||
assertInstanceOf(Page.class, actual.getData());
|
||||
assertEquals(1, ((Page<?>) actual.getData()).getPageItems().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -18,15 +18,12 @@ package com.alibaba.nacos.core.auth;
|
|||
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.auth.config.AuthErrorCode;
|
||||
import com.alibaba.nacos.auth.config.AuthModuleStateBuilder;
|
||||
import com.alibaba.nacos.auth.config.NacosAuthConfig;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.config.AbstractDynamicConfig;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ApiType;
|
||||
import com.alibaba.nacos.plugin.auth.constant.Constants;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.alibaba.nacos.sys.module.ModuleState;
|
||||
import com.alibaba.nacos.sys.module.ModuleStateHolder;
|
||||
import com.alibaba.nacos.sys.utils.PropertiesUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -156,11 +153,6 @@ public class NacosServerAuthConfig extends AbstractDynamicConfig implements Naco
|
|||
serverIdentityKey = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_KEY, "");
|
||||
serverIdentityValue = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_VALUE, "");
|
||||
refreshPluginProperties();
|
||||
ModuleStateHolder.getInstance().getModuleState(AuthModuleStateBuilder.AUTH_MODULE)
|
||||
.ifPresent(moduleState -> {
|
||||
ModuleState temp = new AuthModuleStateBuilder().build();
|
||||
moduleState.getStates().putAll(temp.getStates());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Upgrade auth config from env failed, use old value", e);
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ package com.alibaba.nacos.core.controller.v3;
|
|||
import com.alibaba.nacos.api.annotation.NacosApi;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
import com.alibaba.nacos.core.service.NamespaceOperationService;
|
||||
|
@ -53,7 +53,7 @@ import static com.alibaba.nacos.core.utils.Commons.NACOS_ADMIN_CORE_CONTEXT_V3;
|
|||
*/
|
||||
@NacosApi
|
||||
@RestController
|
||||
@RequestMapping(NACOS_ADMIN_CORE_CONTEXT_V3 + "namespace")
|
||||
@RequestMapping(NACOS_ADMIN_CORE_CONTEXT_V3 + "/namespace")
|
||||
public class NamespaceControllerV3 {
|
||||
|
||||
private final NamespaceOperationService namespaceOperationService;
|
||||
|
@ -116,6 +116,7 @@ public class NamespaceControllerV3 {
|
|||
if (StringUtils.isBlank(namespaceId)) {
|
||||
namespaceId = UUID.randomUUID().toString();
|
||||
} else {
|
||||
// TODO check should be parameter check filter.
|
||||
namespaceId = namespaceId.trim();
|
||||
if (!namespaceIdCheckPattern.matcher(namespaceId).matches()) {
|
||||
throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.ILLEGAL_NAMESPACE,
|
||||
|
@ -125,11 +126,6 @@ public class NamespaceControllerV3 {
|
|||
throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.ILLEGAL_NAMESPACE,
|
||||
"too long namespaceId, over " + NAMESPACE_ID_MAX_LENGTH);
|
||||
}
|
||||
// check unique
|
||||
if (namespacePersistService.tenantInfoCountByTenantId(namespaceId) > 0) {
|
||||
throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.ILLEGAL_NAMESPACE,
|
||||
"the namespaceId is existed, namespaceId: " + namespaceForm.getNamespaceId());
|
||||
}
|
||||
}
|
||||
// contains illegal chars
|
||||
if (!namespaceNameCheckPattern.matcher(namespaceName).matches()) {
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.controller.v3;
|
||||
|
||||
import com.alibaba.nacos.api.annotation.NacosApi;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.core.cluster.health.ModuleHealthCheckerHolder;
|
||||
import com.alibaba.nacos.core.cluster.health.ReadinessResult;
|
||||
import com.alibaba.nacos.core.service.NacosServerStateService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.nacos.core.utils.Commons.NACOS_ADMIN_CORE_CONTEXT_V3;
|
||||
|
||||
/**
|
||||
* Server state controller for admin API.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@NacosApi
|
||||
@RestController
|
||||
@RequestMapping(NACOS_ADMIN_CORE_CONTEXT_V3 + "/state")
|
||||
public class ServerStateController {
|
||||
|
||||
private final NacosServerStateService stateService;
|
||||
|
||||
public ServerStateController(NacosServerStateService stateService) {
|
||||
this.stateService = stateService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server state of current server.
|
||||
*
|
||||
* @return state key-value map.
|
||||
*/
|
||||
@GetMapping()
|
||||
public Result<Map<String, String>> serverState() {
|
||||
return Result.success(stateService.getServerState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the Nacos is in broken states or not, and cannot recover except by being restarted.
|
||||
*
|
||||
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
|
||||
* Nacos is in broken states.
|
||||
*/
|
||||
@GetMapping("/liveness")
|
||||
public Result<String> liveness() {
|
||||
return Result.success("ok");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ready to receive the request or not.
|
||||
*
|
||||
* @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not
|
||||
* ready.
|
||||
*/
|
||||
@GetMapping("/readiness")
|
||||
public Result<String> readiness() throws NacosException {
|
||||
ReadinessResult result = ModuleHealthCheckerHolder.getInstance().checkReadiness();
|
||||
if (result.isSuccess()) {
|
||||
return Result.success("ok");
|
||||
}
|
||||
return Result.failure(result.getResultMessage());
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.alibaba.nacos.core.namespace.injector;
|
||||
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
|
||||
/**
|
||||
* Namespace detail injector.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.alibaba.nacos.core.namespace.injector;
|
||||
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.namespace.model;
|
||||
|
||||
/**
|
||||
* Namespace.
|
||||
*
|
||||
* @author diamond
|
||||
*/
|
||||
public class Namespace {
|
||||
|
||||
private String namespace;
|
||||
|
||||
private String namespaceShowName;
|
||||
|
||||
private String namespaceDesc;
|
||||
|
||||
private int quota;
|
||||
|
||||
private int configCount;
|
||||
|
||||
/**
|
||||
* see {@link NamespaceTypeEnum}.
|
||||
*/
|
||||
private int type;
|
||||
|
||||
public String getNamespaceShowName() {
|
||||
return namespaceShowName;
|
||||
}
|
||||
|
||||
public void setNamespaceShowName(String namespaceShowName) {
|
||||
this.namespaceShowName = namespaceShowName;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public Namespace() {
|
||||
}
|
||||
|
||||
public Namespace(String namespace, String namespaceShowName) {
|
||||
this.namespace = namespace;
|
||||
this.namespaceShowName = namespaceShowName;
|
||||
}
|
||||
|
||||
public Namespace(String namespace, String namespaceShowName, int quota, int configCount, int type) {
|
||||
this.namespace = namespace;
|
||||
this.namespaceShowName = namespaceShowName;
|
||||
this.quota = quota;
|
||||
this.configCount = configCount;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Namespace(String namespace, String namespaceShowName, String namespaceDesc, int quota, int configCount,
|
||||
int type) {
|
||||
this.namespace = namespace;
|
||||
this.namespaceShowName = namespaceShowName;
|
||||
this.quota = quota;
|
||||
this.configCount = configCount;
|
||||
this.type = type;
|
||||
this.namespaceDesc = namespaceDesc;
|
||||
}
|
||||
|
||||
public String getNamespaceDesc() {
|
||||
return namespaceDesc;
|
||||
}
|
||||
|
||||
public void setNamespaceDesc(String namespaceDesc) {
|
||||
this.namespaceDesc = namespaceDesc;
|
||||
}
|
||||
|
||||
public int getQuota() {
|
||||
return quota;
|
||||
}
|
||||
|
||||
public void setQuota(int quota) {
|
||||
this.quota = quota;
|
||||
}
|
||||
|
||||
public int getConfigCount() {
|
||||
return configCount;
|
||||
}
|
||||
|
||||
public void setConfigCount(int configCount) {
|
||||
this.configCount = configCount;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ import java.io.Serializable;
|
|||
/**
|
||||
* TenantInfo.
|
||||
*
|
||||
* <p>Old name of {@link Namespace}</p>
|
||||
* <p>Old name of {@link com.alibaba.nacos.api.model.response.Namespace}</p>
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.service;
|
||||
|
||||
import com.alibaba.nacos.sys.module.ModuleState;
|
||||
import com.alibaba.nacos.sys.module.ModuleStateHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Nacos server state service.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@Service
|
||||
public class NacosServerStateService {
|
||||
|
||||
/**
|
||||
* Get current server states.
|
||||
*
|
||||
* @return server states key-value map.
|
||||
*/
|
||||
public Map<String, String> getServerState() {
|
||||
Map<String, String> serverState = new HashMap<>(4);
|
||||
for (ModuleState each : ModuleStateHolder.getInstance().getAllModuleStates()) {
|
||||
each.getStates().forEach((s, o) -> serverState.put(s, null == o ? null : o.toString()));
|
||||
}
|
||||
return serverState;
|
||||
}
|
||||
}
|
|
@ -18,11 +18,11 @@ package com.alibaba.nacos.core.service;
|
|||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.namespace.injector.NamespaceDetailInjectorHolder;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.NamespaceTypeEnum;
|
||||
import com.alibaba.nacos.core.namespace.model.TenantInfo;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
|
|
|
@ -18,9 +18,9 @@ package com.alibaba.nacos.core.controller.v3;
|
|||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.form.NamespaceForm;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
import com.alibaba.nacos.core.service.NamespaceOperationService;
|
||||
|
@ -102,19 +102,16 @@ class NamespaceControllerV3Test {
|
|||
form.setNamespaceName(TEST_NAMESPACE_NAME);
|
||||
form.setNamespaceDesc(TEST_NAMESPACE_DESC);
|
||||
|
||||
when(namespaceOperationService.createNamespace(
|
||||
TEST_NAMESPACE_ID,
|
||||
TEST_NAMESPACE_NAME,
|
||||
TEST_NAMESPACE_DESC
|
||||
)).thenReturn(true);
|
||||
when(namespaceOperationService.createNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME,
|
||||
TEST_NAMESPACE_DESC)).thenReturn(true);
|
||||
|
||||
Result<Boolean> result = namespaceControllerV3.createNamespace(form);
|
||||
|
||||
Assertions.assertNotNull(result);
|
||||
Assertions.assertEquals(ErrorCode.SUCCESS.getCode(), (int) result.getCode());
|
||||
Assertions.assertTrue(result.getData());
|
||||
verify(namespaceOperationService, times(1))
|
||||
.createNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC);
|
||||
verify(namespaceOperationService, times(1)).createNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME,
|
||||
TEST_NAMESPACE_DESC);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -138,19 +135,15 @@ class NamespaceControllerV3Test {
|
|||
form.setNamespaceName("updated-name");
|
||||
form.setNamespaceDesc("updated-desc");
|
||||
|
||||
when(namespaceOperationService.editNamespace(
|
||||
TEST_NAMESPACE_ID,
|
||||
"updated-name",
|
||||
"updated-desc"
|
||||
)).thenReturn(true);
|
||||
when(namespaceOperationService.editNamespace(TEST_NAMESPACE_ID, "updated-name", "updated-desc")).thenReturn(
|
||||
true);
|
||||
|
||||
Result<Boolean> result = namespaceControllerV3.updateNamespace(form);
|
||||
|
||||
Assertions.assertNotNull(result);
|
||||
Assertions.assertEquals(ErrorCode.SUCCESS.getCode(), (int) result.getCode());
|
||||
Assertions.assertTrue(result.getData());
|
||||
verify(namespaceOperationService, times(1))
|
||||
.editNamespace(TEST_NAMESPACE_ID, "updated-name", "updated-desc");
|
||||
verify(namespaceOperationService, times(1)).editNamespace(TEST_NAMESPACE_ID, "updated-name", "updated-desc");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -21,7 +21,7 @@ import com.alibaba.nacos.api.exception.NacosException;
|
|||
import com.alibaba.nacos.api.exception.api.NacosApiException;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.core.namespace.injector.AbstractNamespaceDetailInjector;
|
||||
import com.alibaba.nacos.core.namespace.model.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.core.namespace.model.NamespaceTypeEnum;
|
||||
import com.alibaba.nacos.core.namespace.model.TenantInfo;
|
||||
import com.alibaba.nacos.core.namespace.repository.NamespacePersistService;
|
||||
|
|
|
@ -190,6 +190,9 @@ nacos.console.port=8080
|
|||
### Nacos Server Web context path:
|
||||
nacos.console.contextPath=
|
||||
|
||||
### Nacos Server context path, which link to nacos server `nacos.server.contextPath`, works when deployment type is `console`
|
||||
nacos.console.remote.server.context-path=/nacos
|
||||
|
||||
#************** Console UI Configuration ***************#
|
||||
|
||||
### Turn on/off the nacos console ui.
|
||||
|
|
|
@ -71,6 +71,8 @@ public class Constants {
|
|||
public static final String CORE_OPS_ADMIN_PATH = "/v3/admin/core/ops";
|
||||
|
||||
public static final String CORE_NAMESPACE_ADMIN_PATH = "/v3/admin/core/namespace";
|
||||
|
||||
public static final String CORE_STATE_ADMIN_PATH = "/v3/admin/core/state";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,6 +52,33 @@ public abstract class AbstractCoreMaintainerService implements CoreMaintainerSer
|
|||
ParamUtil.initSerialization();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getServerState() throws NacosException {
|
||||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.GET)
|
||||
.setPath(Constants.AdminApiPath.CORE_STATE_ADMIN_PATH).build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
Result<Map<String, String>> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Map<String, String>>>() {
|
||||
});
|
||||
return result.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean liveness() throws NacosException {
|
||||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.GET)
|
||||
.setPath(Constants.AdminApiPath.CORE_STATE_ADMIN_PATH + "/liveness").build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
return httpRestResult.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean readiness() throws NacosException {
|
||||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.GET)
|
||||
.setPath(Constants.AdminApiPath.CORE_OPS_ADMIN_PATH + "/readiness").build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
return httpRestResult.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String raftOps(String command, String value, String groupId) throws NacosException {
|
||||
Map<String, String> params = new HashMap<>(8);
|
||||
|
@ -201,8 +228,7 @@ public abstract class AbstractCoreMaintainerService implements CoreMaintainerSer
|
|||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.GET)
|
||||
.setPath(Constants.AdminApiPath.CORE_NAMESPACE_ADMIN_PATH).setParamValue(params).build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
Result<Namespace> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Namespace>>() {
|
||||
Result<Namespace> result = JacksonUtils.toObj(httpRestResult.getData(), new TypeReference<Result<Namespace>>() {
|
||||
});
|
||||
return result.getData();
|
||||
}
|
||||
|
@ -218,8 +244,7 @@ public abstract class AbstractCoreMaintainerService implements CoreMaintainerSer
|
|||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.POST)
|
||||
.setPath(Constants.AdminApiPath.CORE_NAMESPACE_ADMIN_PATH).setParamValue(params).build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
Result<Boolean> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Boolean>>() {
|
||||
Result<Boolean> result = JacksonUtils.toObj(httpRestResult.getData(), new TypeReference<Result<Boolean>>() {
|
||||
});
|
||||
return result.getData();
|
||||
}
|
||||
|
@ -235,8 +260,7 @@ public abstract class AbstractCoreMaintainerService implements CoreMaintainerSer
|
|||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.PUT)
|
||||
.setPath(Constants.AdminApiPath.CORE_NAMESPACE_ADMIN_PATH).setParamValue(params).build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
Result<Boolean> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Boolean>>() {
|
||||
Result<Boolean> result = JacksonUtils.toObj(httpRestResult.getData(), new TypeReference<Result<Boolean>>() {
|
||||
});
|
||||
return result.getData();
|
||||
}
|
||||
|
@ -249,8 +273,7 @@ public abstract class AbstractCoreMaintainerService implements CoreMaintainerSer
|
|||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.DELETE)
|
||||
.setPath(Constants.AdminApiPath.CORE_NAMESPACE_ADMIN_PATH).setParamValue(params).build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
Result<Boolean> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Boolean>>() {
|
||||
Result<Boolean> result = JacksonUtils.toObj(httpRestResult.getData(), new TypeReference<Result<Boolean>>() {
|
||||
});
|
||||
return result.getData();
|
||||
}
|
||||
|
@ -263,8 +286,7 @@ public abstract class AbstractCoreMaintainerService implements CoreMaintainerSer
|
|||
HttpRequest httpRequest = new HttpRequest.Builder().setHttpMethod(HttpMethod.GET)
|
||||
.setPath(Constants.AdminApiPath.CORE_NAMESPACE_ADMIN_PATH + "/check").setParamValue(params).build();
|
||||
HttpRestResult<String> httpRestResult = clientHttpProxy.executeSyncHttpRequest(httpRequest);
|
||||
Result<Integer> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Integer>>() {
|
||||
Result<Integer> result = JacksonUtils.toObj(httpRestResult.getData(), new TypeReference<Result<Integer>>() {
|
||||
});
|
||||
return result.getData() > 0;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.alibaba.nacos.api.model.response.IdGeneratorInfo;
|
|||
import com.alibaba.nacos.api.model.response.NacosMember;
|
||||
import com.alibaba.nacos.api.model.response.Namespace;
|
||||
import com.alibaba.nacos.api.model.response.ServerLoaderMetrics;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -34,6 +35,30 @@ import java.util.Map;
|
|||
*/
|
||||
public interface CoreMaintainerService {
|
||||
|
||||
/**
|
||||
* Get Nacos server states.
|
||||
*
|
||||
* @return the states key-value map
|
||||
* @throws NacosException if the operation fails.
|
||||
*/
|
||||
Map<String, String> getServerState() throws NacosException;
|
||||
|
||||
/**
|
||||
* Detect server liveness.
|
||||
*
|
||||
* @return {@code true} detect successfully, {@code false} otherwise.
|
||||
* @throws NacosException if the operation fails.
|
||||
*/
|
||||
Boolean liveness() throws NacosException;
|
||||
|
||||
/**
|
||||
* Detect server readiness.
|
||||
*
|
||||
* @return {@code true} detect successfully, {@code false} otherwise.
|
||||
* @throws NacosException if the operation fails.
|
||||
*/
|
||||
Boolean readiness() throws NacosException;
|
||||
|
||||
/**
|
||||
* Execute a Raft operation with the specified command, value, and group ID.
|
||||
*
|
||||
|
@ -143,10 +168,22 @@ public interface CoreMaintainerService {
|
|||
*/
|
||||
Namespace getNamespace(String namespaceId) throws NacosException;
|
||||
|
||||
/**
|
||||
* Create a new namespace with the provided details and auto-generate UUID.
|
||||
*
|
||||
* @param namespaceName The name of the new namespace.
|
||||
* @param namespaceDesc The description of the new namespace.
|
||||
* @return {@code true} if the namespace is created successfully, {@code false} otherwise.
|
||||
* @throws NacosException Thrown if any error occurs during the creation.
|
||||
*/
|
||||
default Boolean createNamespace(String namespaceName, String namespaceDesc) throws NacosException {
|
||||
return createNamespace(StringUtils.EMPTY, namespaceName, namespaceDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new namespace with the provided details.
|
||||
*
|
||||
* @param namespaceId The unique identifier for the new namespace.
|
||||
* @param namespaceId The unique identifier for the new namespace, if null or empty will use auto-generate UUID.
|
||||
* @param namespaceName The name of the new namespace.
|
||||
* @param namespaceDesc The description of the new namespace.
|
||||
* @return {@code true} if the namespace is created successfully, {@code false} otherwise.
|
||||
|
@ -159,7 +196,7 @@ public interface CoreMaintainerService {
|
|||
*
|
||||
* @param namespaceId The unique identifier of the namespace to be updated.
|
||||
* @param namespaceName The new name for the namespace (can be null).
|
||||
* @param namespaceDesc The new description for the namespace (can be null).
|
||||
* @param namespaceDesc The new description for the namespace.
|
||||
* @return {@code true} if the namespace is updated successfully, {@code false} otherwise.
|
||||
* @throws NacosException Thrown if any error occurs during the update.
|
||||
*/
|
||||
|
|
|
@ -117,23 +117,23 @@ public class NacosNamingMaintainerServiceImpl extends AbstractCoreMaintainerServ
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceView> listServices(String namespaceId, String groupNameParam, String serviceNameParam,
|
||||
public Page<ServiceView> listServices(String namespaceId, String groupNameParam, String serviceNameParam,
|
||||
boolean ignoreEmptyService, int pageNo, int pageSize) throws NacosException {
|
||||
HttpRestResult<String> httpRestResult = doListServices(namespaceId, groupNameParam, serviceNameParam, false,
|
||||
ignoreEmptyService, pageNo, pageSize);
|
||||
Result<List<ServiceView>> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<List<ServiceView>>>() {
|
||||
Result<Page<ServiceView>> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Page<ServiceView>>>() {
|
||||
});
|
||||
return result.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceDetailInfo> listServicesWithDetail(String namespaceId, String groupNameParam,
|
||||
public Page<ServiceDetailInfo> listServicesWithDetail(String namespaceId, String groupNameParam,
|
||||
String serviceNameParam, int pageNo, int pageSize) throws NacosException {
|
||||
HttpRestResult<String> httpRestResult = doListServices(namespaceId, groupNameParam, serviceNameParam, true,
|
||||
false, pageNo, pageSize);
|
||||
Result<List<ServiceDetailInfo>> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<List<ServiceDetailInfo>>>() {
|
||||
Result<Page<ServiceDetailInfo>> result = JacksonUtils.toObj(httpRestResult.getData(),
|
||||
new TypeReference<Result<Page<ServiceDetailInfo>>>() {
|
||||
});
|
||||
return result.getData();
|
||||
}
|
||||
|
|
|
@ -330,10 +330,10 @@ public interface ServiceMaintainerService {
|
|||
* <p>Only list the first 100 services if this namespace contains more than 100 services</p>
|
||||
*
|
||||
* @param namespaceId target namespace id
|
||||
* @return list of service view, {@link ServiceView} is a summary of service.
|
||||
* @return page of service view, {@link ServiceView} is a summary of service.
|
||||
* @throws NacosException if an error occurs
|
||||
*/
|
||||
default List<ServiceView> listServices(String namespaceId) throws NacosException {
|
||||
default Page<ServiceView> listServices(String namespaceId) throws NacosException {
|
||||
return listServices(namespaceId, StringUtils.EMPTY, StringUtils.EMPTY);
|
||||
}
|
||||
|
||||
|
@ -345,10 +345,10 @@ public interface ServiceMaintainerService {
|
|||
* @param namespaceId target namespace id
|
||||
* @param groupNameParam the group name pattern, e.g., "" for all groups, "group" for all services groupName match `.*group.*`.
|
||||
* @param serviceNameParam the service name pattern, e.g., "" for all services, "service" for all services name match `.*service.*`.
|
||||
* @return list of service view, {@link ServiceView} is a summary of service.
|
||||
* @return page of service view, {@link ServiceView} is a summary of service.
|
||||
* @throws NacosException if an error occurs
|
||||
*/
|
||||
default List<ServiceView> listServices(String namespaceId, String groupNameParam, String serviceNameParam)
|
||||
default Page<ServiceView> listServices(String namespaceId, String groupNameParam, String serviceNameParam)
|
||||
throws NacosException {
|
||||
return listServices(namespaceId, groupNameParam, serviceNameParam, true, 1, 100);
|
||||
}
|
||||
|
@ -364,10 +364,10 @@ public interface ServiceMaintainerService {
|
|||
* @param ignoreEmptyService whether ignore empty service, {@code true} will exclude these services without any instance.
|
||||
* @param pageNo page number, start from 1
|
||||
* @param pageSize page size per page
|
||||
* @return list of service view, {@link ServiceView} is a summary of service.
|
||||
* @return page of service view, {@link ServiceView} is a summary of service.
|
||||
* @throws NacosException if an error occurs
|
||||
*/
|
||||
List<ServiceView> listServices(String namespaceId, String groupNameParam, String serviceNameParam,
|
||||
Page<ServiceView> listServices(String namespaceId, String groupNameParam, String serviceNameParam,
|
||||
boolean ignoreEmptyService, int pageNo, int pageSize) throws NacosException;
|
||||
|
||||
/**
|
||||
|
@ -381,10 +381,10 @@ public interface ServiceMaintainerService {
|
|||
* </p>
|
||||
*
|
||||
* @param namespaceId target namespace id
|
||||
* @return list of service detail, {@link ServiceDetailInfo} is a detail info of service.
|
||||
* @return page of service detail, {@link ServiceDetailInfo} is a detail info of service.
|
||||
* @throws NacosException if an error occurs
|
||||
*/
|
||||
default List<ServiceDetailInfo> listServicesWithDetail(String namespaceId) throws NacosException {
|
||||
default Page<ServiceDetailInfo> listServicesWithDetail(String namespaceId) throws NacosException {
|
||||
return listServicesWithDetail(namespaceId, StringUtils.EMPTY, StringUtils.EMPTY);
|
||||
}
|
||||
|
||||
|
@ -401,10 +401,10 @@ public interface ServiceMaintainerService {
|
|||
* @param namespaceId target namespace id
|
||||
* @param groupNameParam the group name pattern, e.g., "" for all groups, "group" for all services groupName match `.*group.*`.
|
||||
* @param serviceNameParam the service name pattern, e.g., "" for all services, "service" for all services name match `.*service.*`.
|
||||
* @return list of service detail, {@link ServiceDetailInfo} is a detail info of service.
|
||||
* @return page of service detail, {@link ServiceDetailInfo} is a detail info of service.
|
||||
* @throws NacosException if an error occurs
|
||||
*/
|
||||
default List<ServiceDetailInfo> listServicesWithDetail(String namespaceId, String groupNameParam,
|
||||
default Page<ServiceDetailInfo> listServicesWithDetail(String namespaceId, String groupNameParam,
|
||||
String serviceNameParam) throws NacosException {
|
||||
return listServicesWithDetail(namespaceId, groupNameParam, serviceNameParam, 1, 100);
|
||||
}
|
||||
|
@ -423,10 +423,10 @@ public interface ServiceMaintainerService {
|
|||
* @param serviceNameParam the service name pattern, e.g., "" for all services, "service" for all services name match `.*service.*`.
|
||||
* @param pageNo page number, start from 1
|
||||
* @param pageSize page size per page
|
||||
* @return list of service detail, {@link ServiceDetailInfo} is a detail info of service.
|
||||
* @return page of service detail, {@link ServiceDetailInfo} is a detail info of service.
|
||||
* @throws NacosException if an error occurs
|
||||
*/
|
||||
List<ServiceDetailInfo> listServicesWithDetail(String namespaceId, String groupNameParam, String serviceNameParam,
|
||||
Page<ServiceDetailInfo> listServicesWithDetail(String namespaceId, String groupNameParam, String serviceNameParam,
|
||||
int pageNo, int pageSize) throws NacosException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.io.File;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
@ -206,13 +205,8 @@ public class ClientHttpProxy {
|
|||
clientAuthPluginManager.getAuthServiceSpiImplSet().forEach(clientAuthService -> {
|
||||
LoginIdentityContext loginIdentityContext = clientAuthService.getLoginIdentityContext(
|
||||
new RequestResource());
|
||||
if (loginIdentityContext != null) {
|
||||
if (loginIdentityContext.getAllKey().contains(NacosAuthLoginConstant.ACCESSTOKEN)) {
|
||||
Map<String, String> accessToken = new HashMap<>(4);
|
||||
accessToken.put(NacosAuthLoginConstant.ACCESSTOKEN,
|
||||
loginIdentityContext.getParameter(NacosAuthLoginConstant.ACCESSTOKEN));
|
||||
header.addAll(accessToken);
|
||||
}
|
||||
for (String key : loginIdentityContext.getAllKey()) {
|
||||
header.addParam(key, loginIdentityContext.getParameter(key));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.alibaba.nacos.maintainer.client.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.response.ConnectionInfo;
|
||||
import com.alibaba.nacos.api.model.response.IdGeneratorInfo;
|
||||
import com.alibaba.nacos.api.model.response.NacosMember;
|
||||
|
@ -24,6 +25,7 @@ import com.alibaba.nacos.api.model.response.ServerLoaderMetrics;
|
|||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import com.alibaba.nacos.maintainer.client.remote.ClientHttpProxy;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -299,7 +301,6 @@ class AbstractCoreMaintainerServiceTest {
|
|||
@Test
|
||||
void testCreateNamespace() throws Exception {
|
||||
// Arrange
|
||||
String namespaceId = "test-namespace-id";
|
||||
String namespaceName = "test-namespace-name";
|
||||
String namespaceDesc = "test-namespace-desc";
|
||||
HttpRestResult<String> mockHttpRestResult = new HttpRestResult<>();
|
||||
|
@ -308,7 +309,7 @@ class AbstractCoreMaintainerServiceTest {
|
|||
when(clientHttpProxy.executeSyncHttpRequest(any())).thenReturn(mockHttpRestResult);
|
||||
|
||||
// Act
|
||||
Boolean result = coreMaintainerService.createNamespace(namespaceId, namespaceName, namespaceDesc);
|
||||
Boolean result = coreMaintainerService.createNamespace(namespaceName, namespaceDesc);
|
||||
|
||||
// Assert
|
||||
assertTrue(result);
|
||||
|
@ -384,4 +385,46 @@ class AbstractCoreMaintainerServiceTest {
|
|||
assertFalse(result);
|
||||
verify(clientHttpProxy, times(1)).executeSyncHttpRequest(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getServerState() throws JsonProcessingException, NacosException {
|
||||
Map<String, String> serverState = new HashMap<>();
|
||||
serverState.put("key", "value");
|
||||
HttpRestResult<String> mockHttpRestResult = new HttpRestResult<>();
|
||||
mockHttpRestResult.setData(new ObjectMapper().writeValueAsString(new Result<>(serverState))); // 0表示不存在
|
||||
when(clientHttpProxy.executeSyncHttpRequest(any())).thenReturn(mockHttpRestResult);
|
||||
|
||||
Map<String, String> result = coreMaintainerService.getServerState();
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("value", result.get("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void liveness() throws NacosException {
|
||||
HttpRestResult<String> mockHttpRestResult = new HttpRestResult<>();
|
||||
mockHttpRestResult.setCode(200);
|
||||
when(clientHttpProxy.executeSyncHttpRequest(any())).thenReturn(mockHttpRestResult);
|
||||
|
||||
Boolean result = coreMaintainerService.liveness();
|
||||
assertTrue(result);
|
||||
|
||||
mockHttpRestResult.setCode(500);
|
||||
result = coreMaintainerService.liveness();
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void readiness() throws NacosException {
|
||||
HttpRestResult<String> mockHttpRestResult = new HttpRestResult<>();
|
||||
mockHttpRestResult.setCode(200);
|
||||
when(clientHttpProxy.executeSyncHttpRequest(any())).thenReturn(mockHttpRestResult);
|
||||
|
||||
Boolean result = coreMaintainerService.readiness();
|
||||
assertTrue(result);
|
||||
|
||||
mockHttpRestResult.setCode(500);
|
||||
result = coreMaintainerService.readiness();
|
||||
assertFalse(result);
|
||||
}
|
||||
}
|
|
@ -157,53 +157,55 @@ public class NacosNamingMaintainerServiceImplTest {
|
|||
|
||||
@Test
|
||||
void testListServices() throws Exception {
|
||||
List<ServiceView> expected = new ArrayList<>();
|
||||
expected.add(new ServiceView());
|
||||
expected.get(0).setName("testService");
|
||||
expected.get(0).setGroupName("testGroup");
|
||||
Page<ServiceView> expected = new Page<>();
|
||||
expected.getPageItems().add(new ServiceView());
|
||||
expected.getPageItems().get(0).setName("testService");
|
||||
expected.getPageItems().get(0).setGroupName("testGroup");
|
||||
HttpRestResult<String> mockHttpRestResult = new HttpRestResult<>();
|
||||
mockHttpRestResult.setData(new ObjectMapper().writeValueAsString(new Result<>(expected)));
|
||||
|
||||
when(clientHttpProxy.executeSyncHttpRequest(any())).thenReturn(mockHttpRestResult);
|
||||
|
||||
// Act
|
||||
List<ServiceView> result = nacosNamingMaintainerService.listServices("testNamespace");
|
||||
Page<ServiceView> result = nacosNamingMaintainerService.listServices("testNamespace");
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("testService", result.get(0).getName());
|
||||
assertEquals("testGroup", result.get(0).getGroupName());
|
||||
assertEquals(1, result.getPageItems().size());
|
||||
assertEquals("testService", result.getPageItems().get(0).getName());
|
||||
assertEquals("testGroup", result.getPageItems().get(0).getGroupName());
|
||||
verify(clientHttpProxy, times(1)).executeSyncHttpRequest(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListServicesWithDetail() throws Exception {
|
||||
// Arrange
|
||||
String namespaceId = "testNamespace";
|
||||
List<ServiceDetailInfo> expected = new ArrayList<>();
|
||||
expected.add(new ServiceDetailInfo());
|
||||
expected.get(0).setNamespaceId(namespaceId);
|
||||
expected.get(0).setServiceName("testService");
|
||||
expected.get(0).setGroupName("testGroup");
|
||||
expected.get(0).setMetadata(Collections.singletonMap("key", "value"));
|
||||
expected.get(0).setClusterMap(Collections.emptyMap());
|
||||
Page<ServiceDetailInfo> expected = new Page<>();
|
||||
List<ServiceDetailInfo> expectedItem = new ArrayList<>();
|
||||
expected.setPageItems(expectedItem);
|
||||
expected.setTotalCount(1);
|
||||
expectedItem.add(new ServiceDetailInfo());
|
||||
expectedItem.get(0).setNamespaceId("testNamespace");
|
||||
expectedItem.get(0).setServiceName("testService");
|
||||
expectedItem.get(0).setGroupName("testGroup");
|
||||
expectedItem.get(0).setMetadata(Collections.singletonMap("key", "value"));
|
||||
expectedItem.get(0).setClusterMap(Collections.emptyMap());
|
||||
HttpRestResult<String> mockHttpRestResult = new HttpRestResult<>();
|
||||
mockHttpRestResult.setData(new ObjectMapper().writeValueAsString(new Result<>(expected)));
|
||||
|
||||
when(clientHttpProxy.executeSyncHttpRequest(any())).thenReturn(mockHttpRestResult);
|
||||
|
||||
// Act
|
||||
List<ServiceDetailInfo> result = nacosNamingMaintainerService.listServicesWithDetail(namespaceId);
|
||||
Page<ServiceDetailInfo> result = nacosNamingMaintainerService.listServicesWithDetail("testNamespace");
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(namespaceId, result.get(0).getNamespaceId());
|
||||
assertEquals("testService", result.get(0).getServiceName());
|
||||
assertEquals("testGroup", result.get(0).getGroupName());
|
||||
assertEquals(Collections.singletonMap("key", "value"), result.get(0).getMetadata());
|
||||
assertEquals(Collections.emptyMap(), result.get(0).getClusterMap());
|
||||
assertEquals(1, result.getPageItems().size());
|
||||
assertEquals("testNamespace", result.getPageItems().get(0).getNamespaceId());
|
||||
assertEquals("testService", result.getPageItems().get(0).getServiceName());
|
||||
assertEquals("testGroup", result.getPageItems().get(0).getGroupName());
|
||||
assertEquals(Collections.singletonMap("key", "value"), result.getPageItems().get(0).getMetadata());
|
||||
assertEquals(Collections.emptyMap(), result.getPageItems().get(0).getClusterMap());
|
||||
verify(clientHttpProxy, times(1)).executeSyncHttpRequest(any());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.alibaba.nacos.naming.controllers;
|
|||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;
|
||||
import com.alibaba.nacos.api.naming.utils.NamingUtils;
|
||||
|
@ -40,6 +41,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -143,9 +145,13 @@ public class CatalogController {
|
|||
@RequestParam(required = false) boolean hasIpCount) throws NacosException {
|
||||
|
||||
if (withInstances) {
|
||||
ServiceDetailInfo serviceDetailInfo = (ServiceDetailInfo) judgeCatalogService().pageListServiceDetail(
|
||||
Page<ServiceDetailInfo> serviceDetailInfo = judgeCatalogService().pageListServiceDetail(
|
||||
namespaceId, groupName, serviceName, pageNo, pageSize);
|
||||
return com.alibaba.nacos.naming.pojo.ServiceDetailInfo.from(serviceDetailInfo);
|
||||
List<com.alibaba.nacos.naming.pojo.ServiceDetailInfo> result = new LinkedList<>();
|
||||
for (ServiceDetailInfo each : serviceDetailInfo.getPageItems()) {
|
||||
result.add(com.alibaba.nacos.naming.pojo.ServiceDetailInfo.from(each));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return judgeCatalogService().pageListService(namespaceId, groupName, serviceName, pageNo, pageSize,
|
||||
containedInstance, hasIpCount);
|
||||
|
|
|
@ -147,7 +147,7 @@ public class ServiceControllerV3 {
|
|||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* if {@link ServiceListForm#isWithInstances()} is {@code true}, will return list {@link ServiceDetailInfo }
|
||||
* if {@link ServiceListForm#isWithInstances()} is {@code true}, will return page {@link ServiceDetailInfo }
|
||||
* </li>
|
||||
* <li>
|
||||
* if {@link ServiceListForm#isWithInstances()} is {@code false}, will return list {@link ServiceView }
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.alibaba.nacos.naming.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ServiceView;
|
||||
|
@ -48,7 +49,7 @@ public interface CatalogService {
|
|||
* @param groupName group name of service
|
||||
* @param serviceName service name
|
||||
* @param clusterName cluster name of instances
|
||||
* @return instances list
|
||||
* @return instances page object
|
||||
* @throws NacosException exception in query
|
||||
*/
|
||||
List<? extends Instance> listInstances(String namespaceId, String groupName, String serviceName, String clusterName)
|
||||
|
@ -90,11 +91,11 @@ public interface CatalogService {
|
|||
* @param serviceName service name
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @return service list
|
||||
* @return service page object
|
||||
* @throws NacosException exception in query
|
||||
*/
|
||||
Object pageListServiceDetail(String namespaceId, String groupName, String serviceName, int pageNo, int pageSize)
|
||||
throws NacosException;
|
||||
Page<ServiceDetailInfo> pageListServiceDetail(String namespaceId, String groupName, String serviceName, int pageNo,
|
||||
int pageSize) throws NacosException;
|
||||
|
||||
/**
|
||||
* List service by page.
|
||||
|
@ -105,10 +106,10 @@ public interface CatalogService {
|
|||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @param ignoreEmptyService whether ignore empty service
|
||||
* @return service list
|
||||
* @return service page object
|
||||
* @throws NacosException exception in query
|
||||
*/
|
||||
List<ServiceView> listService(String namespaceId, String groupName, String serviceName, int pageNo, int pageSize,
|
||||
Page<ServiceView> listService(String namespaceId, String groupName, String serviceName, int pageNo, int pageSize,
|
||||
boolean ignoreEmptyService) throws NacosException;
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.alibaba.nacos.naming.core;
|
|||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ClusterInfo;
|
||||
|
@ -37,7 +38,6 @@ import com.alibaba.nacos.naming.utils.ServiceUtil;
|
|||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -161,15 +161,17 @@ public class CatalogServiceV2Impl implements CatalogService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceView> listService(String namespaceId, String groupName, String serviceName, int pageNo,
|
||||
public Page<ServiceView> listService(String namespaceId, String groupName, String serviceName, int pageNo,
|
||||
int pageSize, boolean ignoreEmptyService) throws NacosException {
|
||||
List<ServiceView> serviceViews = new LinkedList<>();
|
||||
Page<ServiceView> serviceViews = new Page<>();
|
||||
Collection<Service> services = patternServices(namespaceId, groupName, serviceName);
|
||||
if (ignoreEmptyService) {
|
||||
services = services.stream().filter(each -> 0 != serviceStorage.getData(each).ipCount())
|
||||
.collect(Collectors.toList());
|
||||
services = services.stream().filter(each -> 0 != serviceStorage.getData(each).ipCount()).toList();
|
||||
}
|
||||
services = PageUtil.subPageList(services.stream().toList(), pageNo, pageSize);
|
||||
Page<Service> page = PageUtil.subPage(services.stream().toList(), pageNo, pageSize);
|
||||
serviceViews.setTotalCount(page.getTotalCount());
|
||||
serviceViews.setPageNumber(page.getPageNumber());
|
||||
serviceViews.setPagesAvailable(page.getPagesAvailable());
|
||||
for (Service each : services) {
|
||||
ServiceMetadata serviceMetadata = metadataManager.getServiceMetadata(each).orElseGet(ServiceMetadata::new);
|
||||
ServiceView serviceView = new ServiceView();
|
||||
|
@ -179,7 +181,7 @@ public class CatalogServiceV2Impl implements CatalogService {
|
|||
serviceView.setIpCount(serviceStorage.getData(each).ipCount());
|
||||
serviceView.setHealthyInstanceCount(countHealthyInstance(serviceStorage.getData(each)));
|
||||
serviceView.setTriggerFlag(isProtectThreshold(serviceView, serviceMetadata) ? "true" : "false");
|
||||
serviceViews.add(serviceView);
|
||||
serviceViews.getPageItems().add(serviceView);
|
||||
}
|
||||
return serviceViews;
|
||||
}
|
||||
|
@ -200,20 +202,25 @@ public class CatalogServiceV2Impl implements CatalogService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object pageListServiceDetail(String namespaceId, String groupName, String serviceName, int pageNo,
|
||||
int pageSize) throws NacosException {
|
||||
List<ServiceDetailInfo> result = new ArrayList<>();
|
||||
public Page<ServiceDetailInfo> pageListServiceDetail(String namespaceId, String groupName, String serviceName,
|
||||
int pageNo, int pageSize) throws NacosException {
|
||||
Collection<Service> services = patternServices(namespaceId, groupName, serviceName);
|
||||
services = doPage(services, pageNo - 1, pageSize);
|
||||
for (Service each : services) {
|
||||
Page<Service> servicePage = PageUtil.subPage(services.stream().toList(), pageNo, pageSize);
|
||||
Page<ServiceDetailInfo> result = new Page<>();
|
||||
result.setPagesAvailable(servicePage.getPagesAvailable());
|
||||
result.setPageNumber(servicePage.getPageNumber());
|
||||
result.setTotalCount(servicePage.getTotalCount());
|
||||
List<ServiceDetailInfo> pagedItem = new LinkedList<>();
|
||||
for (Service each : servicePage.getPageItems()) {
|
||||
ServiceDetailInfo serviceDetailInfo = new ServiceDetailInfo();
|
||||
serviceDetailInfo.setServiceName(each.getName());
|
||||
serviceDetailInfo.setGroupName(each.getGroup());
|
||||
ServiceMetadata serviceMetadata = metadataManager.getServiceMetadata(each).orElseGet(ServiceMetadata::new);
|
||||
serviceDetailInfo.setMetadata(serviceMetadata.getExtendData());
|
||||
serviceDetailInfo.setClusterMap(getClusterMap(each));
|
||||
result.add(serviceDetailInfo);
|
||||
pagedItem.add(serviceDetailInfo);
|
||||
}
|
||||
result.setPageItems(pagedItem);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
#
|
||||
# Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
server.port=8848
|
||||
server.servlet.context-path=/nacos
|
||||
# Number of ms to wait before throwing an exception if no connection is available.
|
||||
spring.datasource.max-wait=10000
|
||||
# Maximum number of active connections that can be allocated from this pool at the same time.
|
||||
spring.datasource.max-active=15
|
||||
## Validate the connection before borrowing it from the pool.
|
||||
#spring.datasource.test-on-borrow=true
|
||||
management.metrics.export.elastic.enabled=false
|
||||
#management.metrics.export.elastic.host=http://localhost:9200
|
||||
# metrics for influx
|
||||
management.metrics.export.influx.enabled=false
|
||||
#management.metrics.export.influx.db=springboot
|
||||
#management.metrics.export.influx.uri=http://localhost:8086
|
||||
#management.metrics.export.influx.auto-create-db=true
|
||||
#management.metrics.export.influx.consistency=one
|
||||
#management.metrics.export.influx.compressed=true
|
||||
server.tomcat.accesslog.enabled=true
|
||||
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D
|
||||
# default current work dir
|
||||
server.tomcat.basedir=file:.
|
|
@ -18,6 +18,7 @@ package com.alibaba.nacos.naming.controllers;
|
|||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;
|
||||
import com.alibaba.nacos.naming.core.CatalogServiceV2Impl;
|
||||
|
@ -30,7 +31,6 @@ import org.mockito.Mock;
|
|||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -93,7 +93,7 @@ class CatalogControllerTest {
|
|||
void testListDetail() {
|
||||
try {
|
||||
when(catalogServiceV2.pageListServiceDetail(Constants.DEFAULT_NAMESPACE_ID, TEST_GROUP_NAME,
|
||||
TEST_SERVICE_NAME, 1, 10)).thenReturn(Collections.emptyList());
|
||||
TEST_SERVICE_NAME, 1, 10)).thenReturn(new Page<>());
|
||||
Object res = catalogController.listDetail(true, Constants.DEFAULT_NAMESPACE_ID, 1, 10, TEST_SERVICE_NAME,
|
||||
TEST_GROUP_NAME, null, true);
|
||||
assertTrue(res instanceof List);
|
||||
|
|
|
@ -156,8 +156,8 @@ class ServiceControllerV3Test {
|
|||
|
||||
@Test
|
||||
void testList() throws Exception {
|
||||
List<ServiceView> result = new LinkedList<>();
|
||||
result.add(new ServiceView());
|
||||
Page<ServiceView> result = new Page<>();
|
||||
result.getPageItems().add(new ServiceView());
|
||||
when(catalogServiceV2.listService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, "serviceName", 1,
|
||||
10, false)).thenReturn(result);
|
||||
ServiceListForm serviceListForm = new ServiceListForm();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package com.alibaba.nacos.naming.core;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.naming.pojo.Instance;
|
||||
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
|
||||
import com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;
|
||||
|
@ -191,10 +192,9 @@ class CatalogServiceV2ImplTest {
|
|||
serviceInfo.setHosts(instances);
|
||||
Mockito.when(serviceStorage.getData(Mockito.any())).thenReturn(serviceInfo);
|
||||
|
||||
List<ServiceDetailInfo> result = (List<ServiceDetailInfo>) catalogServiceV2Impl.pageListServiceDetail("A",
|
||||
"B", "C", 1, 10);
|
||||
Page<ServiceDetailInfo> result = catalogServiceV2Impl.pageListServiceDetail("A", "B", "C", 1, 10);
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(1, result.getPageItems().size());
|
||||
} catch (NacosException e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
|
|
|
@ -22,13 +22,12 @@ import com.alibaba.nacos.core.utils.Loggers;
|
|||
import com.alibaba.nacos.plugin.auth.api.Permission;
|
||||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetails;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
|
@ -39,14 +38,14 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||
*/
|
||||
public class AbstractAuthenticationManager implements IAuthenticationManager {
|
||||
|
||||
protected NacosUserDetailsServiceImpl userDetailsService;
|
||||
protected NacosUserService userDetailsService;
|
||||
|
||||
protected TokenManagerDelegate jwtTokenManager;
|
||||
|
||||
protected NacosRoleServiceImpl roleService;
|
||||
protected NacosRoleService roleService;
|
||||
|
||||
public AbstractAuthenticationManager(NacosUserDetailsServiceImpl userDetailsService,
|
||||
TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService) {
|
||||
public AbstractAuthenticationManager(NacosUserService userDetailsService, TokenManagerDelegate jwtTokenManager,
|
||||
NacosRoleService roleService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.jwtTokenManager = jwtTokenManager;
|
||||
this.roleService = roleService;
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
package com.alibaba.nacos.plugin.auth.impl.authenticate;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
|
||||
/**
|
||||
* DefaultAuthenticationManager.
|
||||
|
@ -28,8 +28,8 @@ import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
|||
*/
|
||||
public class DefaultAuthenticationManager extends AbstractAuthenticationManager {
|
||||
|
||||
public DefaultAuthenticationManager(NacosUserDetailsServiceImpl userDetailsService,
|
||||
TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService) {
|
||||
public DefaultAuthenticationManager(NacosUserService userDetailsService, TokenManagerDelegate jwtTokenManager,
|
||||
NacosRoleService roleService) {
|
||||
super(userDetailsService, jwtTokenManager, roleService);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ import com.alibaba.nacos.core.utils.Loggers;
|
|||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetails;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.filter.EqualsFilter;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
@ -45,8 +45,8 @@ public class LdapAuthenticationManager extends AbstractAuthenticationManager {
|
|||
|
||||
private final LdapTemplate ldapTemplate;
|
||||
|
||||
public LdapAuthenticationManager(LdapTemplate ldapTemplate, NacosUserDetailsServiceImpl userDetailsService,
|
||||
TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService, String filterPrefix,
|
||||
public LdapAuthenticationManager(LdapTemplate ldapTemplate, NacosUserService userDetailsService,
|
||||
TokenManagerDelegate jwtTokenManager, NacosRoleService roleService, String filterPrefix,
|
||||
boolean caseSensitive) {
|
||||
super(userDetailsService, jwtTokenManager, roleService);
|
||||
this.ldapTemplate = ldapTemplate;
|
||||
|
@ -80,7 +80,7 @@ public class LdapAuthenticationManager extends AbstractAuthenticationManager {
|
|||
userDetails = userDetailsService.loadUserByUsername(AuthConstants.LDAP_PREFIX + username);
|
||||
} catch (UsernameNotFoundException exception) {
|
||||
String ldapUsername = AuthConstants.LDAP_PREFIX + username;
|
||||
userDetailsService.createUser(ldapUsername, AuthConstants.LDAP_DEFAULT_ENCODED_PASSWORD);
|
||||
userDetailsService.createUser(ldapUsername, AuthConstants.LDAP_DEFAULT_ENCODED_PASSWORD, false);
|
||||
User user = new User();
|
||||
user.setUsername(ldapUsername);
|
||||
user.setPassword(AuthConstants.LDAP_DEFAULT_ENCODED_PASSWORD);
|
||||
|
|
|
@ -23,12 +23,12 @@ import com.alibaba.nacos.core.code.ControllerMethodsCache;
|
|||
import com.alibaba.nacos.plugin.auth.impl.authenticate.DefaultAuthenticationManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.impl.CachedJwtTokenManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.impl.JwtTokenManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -48,11 +48,11 @@ import javax.annotation.PostConstruct;
|
|||
@Configuration
|
||||
public class NacosAuthPluginConfig {
|
||||
|
||||
private final NacosUserDetailsServiceImpl userDetailsService;
|
||||
private final NacosUserService userDetailsService;
|
||||
|
||||
private final ControllerMethodsCache methodsCache;
|
||||
|
||||
public NacosAuthPluginConfig(NacosUserDetailsServiceImpl userDetailsService, ControllerMethodsCache methodsCache) {
|
||||
public NacosAuthPluginConfig(NacosUserService userDetailsService, ControllerMethodsCache methodsCache) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.methodsCache = methodsCache;
|
||||
|
||||
|
@ -88,8 +88,8 @@ public class NacosAuthPluginConfig {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public IAuthenticationManager defaultAuthenticationManager(NacosUserDetailsServiceImpl userDetailsService,
|
||||
TokenManagerDelegate jwtTokenManager, NacosRoleServiceImpl roleService) {
|
||||
public IAuthenticationManager defaultAuthenticationManager(NacosUserService userDetailsService,
|
||||
TokenManagerDelegate jwtTokenManager, NacosRoleService roleService) {
|
||||
return new DefaultAuthenticationManager(userDetailsService, jwtTokenManager, roleService);
|
||||
}
|
||||
|
||||
|
|
|
@ -79,4 +79,13 @@ public class AuthConstants {
|
|||
public static final String LDAP_DEFAULT_ENCODED_PASSWORD = PasswordEncoderUtil.encode(System.getProperty("ldap.default.password", "nacos"));
|
||||
|
||||
public static final String LDAP_PREFIX = "LDAP_";
|
||||
|
||||
/**
|
||||
* Path for nacos plugin controller.
|
||||
*/
|
||||
public static final String USER_PATH = "/v3/auth/user";
|
||||
|
||||
public static final String ROLE_PATH = "/v3/auth/role";
|
||||
|
||||
public static final String PERMISSION_PATH = "/v3/auth/permission";
|
||||
}
|
||||
|
|
|
@ -16,17 +16,17 @@
|
|||
|
||||
package com.alibaba.nacos.plugin.auth.impl.controller;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.controller.compatibility.Compatibility;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ApiType;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -46,7 +46,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
public class PermissionController {
|
||||
|
||||
@Autowired
|
||||
private NacosRoleServiceImpl nacosRoleService;
|
||||
private NacosRoleService nacosRoleService;
|
||||
|
||||
/**
|
||||
* Query permissions of a role.
|
||||
|
@ -61,7 +61,7 @@ public class PermissionController {
|
|||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/auth/permission/list")
|
||||
public Object getPermissions(@RequestParam int pageNo, @RequestParam int pageSize,
|
||||
@RequestParam(name = "role", defaultValue = StringUtils.EMPTY) String role) {
|
||||
return nacosRoleService.getPermissionsFromDatabase(role, pageNo, pageSize);
|
||||
return nacosRoleService.getPermissions(role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,7 +77,7 @@ public class PermissionController {
|
|||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/auth/permission/list")
|
||||
public Page<PermissionInfo> fuzzySearchPermission(@RequestParam int pageNo, @RequestParam int pageSize,
|
||||
@RequestParam(name = "role", defaultValue = StringUtils.EMPTY) String role) {
|
||||
return nacosRoleService.findPermissionsLike4Page(role, pageNo, pageSize);
|
||||
return nacosRoleService.findPermissions(role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,7 +124,8 @@ public class PermissionController {
|
|||
@GetMapping
|
||||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.READ)
|
||||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/auth/permission")
|
||||
public Result<Boolean> isDuplicatePermission(@RequestParam String role, @RequestParam String resource, @RequestParam String action) {
|
||||
public Result<Boolean> isDuplicatePermission(@RequestParam String role, @RequestParam String resource,
|
||||
@RequestParam String action) {
|
||||
return nacosRoleService.isDuplicatePermission(role, resource, action);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
package com.alibaba.nacos.plugin.auth.impl.controller;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.controller.compatibility.Compatibility;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ApiType;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -47,7 +47,7 @@ import java.util.List;
|
|||
public class RoleController {
|
||||
|
||||
@Autowired
|
||||
private NacosRoleServiceImpl roleService;
|
||||
private NacosRoleService roleService;
|
||||
|
||||
/**
|
||||
* Get roles list.
|
||||
|
@ -64,7 +64,7 @@ public class RoleController {
|
|||
public Object getRoles(@RequestParam int pageNo, @RequestParam int pageSize,
|
||||
@RequestParam(name = "username", defaultValue = "") String username,
|
||||
@RequestParam(name = "role", defaultValue = "") String role) {
|
||||
return roleService.getRolesFromDatabase(username, role, pageNo, pageSize);
|
||||
return roleService.getRoles(username, role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,7 +81,7 @@ public class RoleController {
|
|||
public Page<RoleInfo> fuzzySearchRole(@RequestParam int pageNo, @RequestParam int pageSize,
|
||||
@RequestParam(name = "username", defaultValue = "") String username,
|
||||
@RequestParam(name = "role", defaultValue = "") String role) {
|
||||
return roleService.findRolesLike4Page(username, role, pageNo, pageSize);
|
||||
return roleService.findRoles(username, role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,7 +94,7 @@ public class RoleController {
|
|||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
|
||||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/auth/role/search")
|
||||
public List<String> searchRoles(@RequestParam String role) {
|
||||
return roleService.findRolesLikeRoleName(role);
|
||||
return roleService.findRoleNames(role);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.alibaba.nacos.plugin.auth.impl.controller;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
|
@ -24,7 +25,6 @@ import com.alibaba.nacos.common.utils.JacksonUtils;
|
|||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.context.RequestContextHolder;
|
||||
import com.alibaba.nacos.core.controller.compatibility.Compatibility;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ApiType;
|
||||
|
@ -34,13 +34,14 @@ import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
|||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordGeneratorUtil;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
|
@ -57,8 +58,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -80,10 +79,10 @@ public class UserController {
|
|||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Autowired
|
||||
private NacosUserDetailsServiceImpl userDetailsService;
|
||||
private NacosUserService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private NacosRoleServiceImpl roleService;
|
||||
private NacosRoleService roleService;
|
||||
|
||||
@Autowired
|
||||
private AuthConfigs authConfigs;
|
||||
|
@ -109,11 +108,11 @@ public class UserController {
|
|||
"User `nacos` is default admin user. Please use `/nacos/v1/auth/users/admin` API to init `nacos` users. "
|
||||
+ "Detail see `https://nacos.io/docs/latest/manual/admin/auth/#31-%E8%AE%BE%E7%BD%AE%E7%AE%A1%E7%90%86%E5%91%98%E5%AF%86%E7%A0%81`");
|
||||
}
|
||||
User user = userDetailsService.getUserFromDatabase(username);
|
||||
User user = userDetailsService.getUser(username);
|
||||
if (user != null) {
|
||||
throw new IllegalArgumentException("user '" + username + "' already exist!");
|
||||
}
|
||||
userDetailsService.createUser(username, PasswordEncoderUtil.encode(password));
|
||||
userDetailsService.createUser(username, password);
|
||||
return RestResultUtils.success("create user ok!");
|
||||
}
|
||||
|
||||
|
@ -132,7 +131,7 @@ public class UserController {
|
|||
}
|
||||
|
||||
String username = AuthConstants.DEFAULT_USER;
|
||||
userDetailsService.createUser(username, PasswordEncoderUtil.encode(password));
|
||||
userDetailsService.createUser(username, password);
|
||||
roleService.addAdminRole(username);
|
||||
ObjectNode result = JacksonUtils.createEmptyJsonNode();
|
||||
result.put(AuthConstants.PARAM_USERNAME, username);
|
||||
|
@ -197,12 +196,12 @@ public class UserController {
|
|||
return null;
|
||||
}
|
||||
|
||||
User user = userDetailsService.getUserFromDatabase(username);
|
||||
User user = userDetailsService.getUser(username);
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("user " + username + " not exist!");
|
||||
}
|
||||
|
||||
userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));
|
||||
userDetailsService.updateUserPassword(username, newPassword);
|
||||
|
||||
return RestResultUtils.success("update user ok!");
|
||||
}
|
||||
|
@ -246,7 +245,7 @@ public class UserController {
|
|||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/auth/user/list")
|
||||
public Page<User> getUsers(@RequestParam int pageNo, @RequestParam int pageSize,
|
||||
@RequestParam(name = "username", required = false, defaultValue = "") String username) {
|
||||
return userDetailsService.getUsersFromDatabase(pageNo, pageSize, username);
|
||||
return userDetailsService.getUsers(pageNo, pageSize, username);
|
||||
}
|
||||
|
||||
@GetMapping(params = "search=blur")
|
||||
|
@ -254,7 +253,7 @@ public class UserController {
|
|||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/auth/user/list")
|
||||
public Page<User> fuzzySearchUser(@RequestParam int pageNo, @RequestParam int pageSize,
|
||||
@RequestParam(name = "username", required = false, defaultValue = "") String username) {
|
||||
return userDetailsService.findUsersLike4Page(username, pageNo, pageSize);
|
||||
return userDetailsService.findUsers(username, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,6 +317,6 @@ public class UserController {
|
|||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
|
||||
@Compatibility(apiType = ApiType.CONSOLE_API, alternatives = "GET ${contextPath:nacos}/v3/auth/user/search")
|
||||
public List<String> searchUsersLikeUsername(@RequestParam String username) {
|
||||
return userDetailsService.findUserLikeUsername(username);
|
||||
return userDetailsService.findUserNames(username);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,16 +17,16 @@
|
|||
|
||||
package com.alibaba.nacos.plugin.auth.impl.controller.v3;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -41,11 +41,11 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
* @author zhangyukun on:2024/8/16
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/v3/auth/permission")
|
||||
@RequestMapping(AuthConstants.PERMISSION_PATH)
|
||||
@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)
|
||||
public class PermissionControllerV3 {
|
||||
|
||||
private final NacosRoleServiceImpl nacosRoleService;
|
||||
private final NacosRoleService nacosRoleService;
|
||||
|
||||
private static final String SEARCH_TYPE_BLUR = "blur";
|
||||
|
||||
|
@ -55,7 +55,7 @@ public class PermissionControllerV3 {
|
|||
* @param nacosRoleService nacosRoleService instance
|
||||
*/
|
||||
@Autowired
|
||||
public PermissionControllerV3(NacosRoleServiceImpl nacosRoleService) {
|
||||
public PermissionControllerV3(NacosRoleService nacosRoleService) {
|
||||
this.nacosRoleService = nacosRoleService;
|
||||
}
|
||||
|
||||
|
@ -69,12 +69,12 @@ public class PermissionControllerV3 {
|
|||
*/
|
||||
@PostMapping
|
||||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.WRITE)
|
||||
public Result<String> createPermission(@RequestParam String role, @RequestParam String resource, @RequestParam String action) {
|
||||
public Result<String> createPermission(@RequestParam String role, @RequestParam String resource,
|
||||
@RequestParam String action) {
|
||||
nacosRoleService.addPermission(role, resource, action);
|
||||
return Result.success("add permission ok!");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete a permission from a role.
|
||||
*
|
||||
|
@ -107,9 +107,9 @@ public class PermissionControllerV3 {
|
|||
@RequestParam(name = "search", defaultValue = "accurate") String search) {
|
||||
Page<PermissionInfo> permissionPage;
|
||||
if (SEARCH_TYPE_BLUR.equalsIgnoreCase(search)) {
|
||||
permissionPage = nacosRoleService.findPermissionsLike4Page(role, pageNo, pageSize);
|
||||
permissionPage = nacosRoleService.findPermissions(role, pageNo, pageSize);
|
||||
} else {
|
||||
permissionPage = nacosRoleService.getPermissionsFromDatabase(role, pageNo, pageSize);
|
||||
permissionPage = nacosRoleService.getPermissions(role, pageNo, pageSize);
|
||||
}
|
||||
return Result.success(permissionPage);
|
||||
}
|
||||
|
@ -124,7 +124,8 @@ public class PermissionControllerV3 {
|
|||
*/
|
||||
@GetMapping
|
||||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.READ)
|
||||
public Result<Boolean> isDuplicatePermission(@RequestParam String role, @RequestParam String resource, @RequestParam String action) {
|
||||
public Result<Boolean> isDuplicatePermission(@RequestParam String role, @RequestParam String resource,
|
||||
@RequestParam String action) {
|
||||
return nacosRoleService.isDuplicatePermission(role, resource, action);
|
||||
}
|
||||
}
|
|
@ -17,16 +17,16 @@
|
|||
|
||||
package com.alibaba.nacos.plugin.auth.impl.controller.v3;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
@ -42,15 +42,15 @@ import java.util.List;
|
|||
* @author zhangyukun on:2024/8/16
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/v3/auth/role")
|
||||
@RequestMapping(AuthConstants.ROLE_PATH)
|
||||
@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)
|
||||
public class RoleControllerV3 {
|
||||
|
||||
private final NacosRoleServiceImpl roleService;
|
||||
private final NacosRoleService roleService;
|
||||
|
||||
private static final String SEARCH_TYPE_BLUR = "blur";
|
||||
|
||||
public RoleControllerV3(NacosRoleServiceImpl roleService) {
|
||||
public RoleControllerV3(NacosRoleService roleService) {
|
||||
this.roleService = roleService;
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,9 @@ public class RoleControllerV3 {
|
|||
@RequestParam(name = "search", required = false, defaultValue = "accurate") String search) {
|
||||
Page<RoleInfo> rolePage;
|
||||
if (SEARCH_TYPE_BLUR.equalsIgnoreCase(search)) {
|
||||
rolePage = roleService.findRolesLike4Page(username, role, pageNo, pageSize);
|
||||
rolePage = roleService.findRoles(username, role, pageNo, pageSize);
|
||||
} else {
|
||||
rolePage = roleService.getRolesFromDatabase(username, role, pageNo, pageSize);
|
||||
rolePage = roleService.getRoles(username, role, pageNo, pageSize);
|
||||
}
|
||||
return Result.success(rolePage);
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ public class RoleControllerV3 {
|
|||
@GetMapping("/search")
|
||||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
|
||||
public Result<List<String>> getRoleListByRoleName(@RequestParam String role) {
|
||||
List<String> roles = roleService.findRolesLikeRoleName(role);
|
||||
List<String> roles = roleService.findRoleNames(role);
|
||||
return Result.success(roles);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package com.alibaba.nacos.plugin.auth.impl.controller.v3;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.ErrorCode;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
|
@ -26,7 +27,6 @@ import com.alibaba.nacos.common.utils.JacksonUtils;
|
|||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;
|
||||
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.api.IdentityContext;
|
||||
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
|
||||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
|
@ -35,11 +35,10 @@ import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
|||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthSystemTypes;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordGeneratorUtil;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
@ -63,13 +62,13 @@ import java.util.List;
|
|||
* @author zhangyukun on:2024/8/16
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/v3/auth/user")
|
||||
@RequestMapping(AuthConstants.USER_PATH)
|
||||
@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)
|
||||
public class UserControllerV3 {
|
||||
|
||||
private final NacosUserDetailsServiceImpl userDetailsService;
|
||||
private final NacosUserService userDetailsService;
|
||||
|
||||
private final NacosRoleServiceImpl roleService;
|
||||
private final NacosRoleService roleService;
|
||||
|
||||
private final AuthConfigs authConfigs;
|
||||
|
||||
|
@ -88,9 +87,8 @@ public class UserControllerV3 {
|
|||
* @param iAuthenticationManager the authentication manager interface
|
||||
* @param jwtTokenManager the JWT token manager
|
||||
*/
|
||||
public UserControllerV3(NacosUserDetailsServiceImpl userDetailsService, NacosRoleServiceImpl roleService,
|
||||
AuthConfigs authConfigs, IAuthenticationManager iAuthenticationManager,
|
||||
TokenManagerDelegate jwtTokenManager) {
|
||||
public UserControllerV3(NacosUserService userDetailsService, NacosRoleService roleService, AuthConfigs authConfigs,
|
||||
IAuthenticationManager iAuthenticationManager, TokenManagerDelegate jwtTokenManager) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.roleService = roleService;
|
||||
this.authConfigs = authConfigs;
|
||||
|
@ -110,11 +108,11 @@ public class UserControllerV3 {
|
|||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
|
||||
@PostMapping
|
||||
public Result<String> createUser(@RequestParam String username, @RequestParam String password) {
|
||||
User user = userDetailsService.getUserFromDatabase(username);
|
||||
User user = userDetailsService.getUser(username);
|
||||
if (user != null) {
|
||||
throw new IllegalArgumentException("user '" + username + "' already exist!");
|
||||
}
|
||||
userDetailsService.createUser(username, PasswordEncoderUtil.encode(password));
|
||||
userDetailsService.createUser(username, password);
|
||||
return Result.success("create user ok!");
|
||||
}
|
||||
|
||||
|
@ -133,7 +131,7 @@ public class UserControllerV3 {
|
|||
return Result.failure(HttpStatus.CONFLICT.value(), "have admin user cannot use it.", null);
|
||||
}
|
||||
String username = AuthConstants.DEFAULT_USER;
|
||||
userDetailsService.createUser(username, PasswordEncoderUtil.encode(password));
|
||||
userDetailsService.createUser(username, password);
|
||||
roleService.addAdminRole(username);
|
||||
User result = new User();
|
||||
result.setUsername(username);
|
||||
|
@ -195,12 +193,12 @@ public class UserControllerV3 {
|
|||
return null;
|
||||
}
|
||||
|
||||
User user = userDetailsService.getUserFromDatabase(username);
|
||||
User user = userDetailsService.getUser(username);
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("user " + username + " not exist!");
|
||||
}
|
||||
|
||||
userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));
|
||||
userDetailsService.updateUserPassword(username, newPassword);
|
||||
return Result.success("update user ok!");
|
||||
|
||||
}
|
||||
|
@ -249,9 +247,9 @@ public class UserControllerV3 {
|
|||
@RequestParam(name = "search", required = false, defaultValue = "accurate") String search) {
|
||||
Page<User> userPage;
|
||||
if (SEARCH_TYPE_BLUR.equalsIgnoreCase(search)) {
|
||||
userPage = userDetailsService.findUsersLike4Page(username, pageNo, pageSize);
|
||||
userPage = userDetailsService.findUsers(username, pageNo, pageSize);
|
||||
} else {
|
||||
userPage = userDetailsService.getUsersFromDatabase(pageNo, pageSize, username);
|
||||
userPage = userDetailsService.getUsers(pageNo, pageSize, username);
|
||||
}
|
||||
return Result.success(userPage);
|
||||
}
|
||||
|
@ -265,7 +263,7 @@ public class UserControllerV3 {
|
|||
@GetMapping("/search")
|
||||
@Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
|
||||
public Result<List<String>> getUserListByUsername(@RequestParam String username) {
|
||||
List<String> userList = userDetailsService.findUserLikeUsername(username);
|
||||
List<String> userList = userDetailsService.findUserNames(username);
|
||||
return Result.success(userList);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ import com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager;
|
|||
import com.alibaba.nacos.plugin.auth.impl.authenticate.LdapAuthenticationManager;
|
||||
import com.alibaba.nacos.plugin.auth.impl.configuration.ConditionOnLdapAuth;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
|
||||
|
@ -85,15 +85,14 @@ public class LdapAuthPluginConfig {
|
|||
|
||||
@Bean
|
||||
public LdapAuthenticationProvider ldapAuthenticationProvider(LdapTemplate ldapTemplate,
|
||||
NacosUserDetailsServiceImpl userDetailsService, NacosRoleServiceImpl nacosRoleService) {
|
||||
NacosUserService userDetailsService, NacosRoleService nacosRoleService) {
|
||||
return new LdapAuthenticationProvider(ldapTemplate, userDetailsService, nacosRoleService, filterPrefix,
|
||||
caseSensitive);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IAuthenticationManager ldapAuthenticatoinManager(LdapTemplate ldapTemplate,
|
||||
NacosUserDetailsServiceImpl userDetailsService, TokenManagerDelegate jwtTokenManager,
|
||||
NacosRoleServiceImpl roleService) {
|
||||
NacosUserService userDetailsService, TokenManagerDelegate jwtTokenManager, NacosRoleService roleService) {
|
||||
return new LdapAuthenticationManager(ldapTemplate, userDetailsService, jwtTokenManager, roleService,
|
||||
filterPrefix, caseSensitive);
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ import com.alibaba.nacos.core.utils.Loggers;
|
|||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetails;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
|
@ -44,9 +44,9 @@ import java.util.List;
|
|||
@Deprecated
|
||||
public class LdapAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
private final NacosUserDetailsServiceImpl userDetailsService;
|
||||
private final NacosUserService userDetailsService;
|
||||
|
||||
private final NacosRoleServiceImpl nacosRoleService;
|
||||
private final NacosRoleService nacosRoleService;
|
||||
|
||||
private final LdapTemplate ldapTemplate;
|
||||
|
||||
|
@ -54,8 +54,8 @@ public class LdapAuthenticationProvider implements AuthenticationProvider {
|
|||
|
||||
private final boolean caseSensitive;
|
||||
|
||||
public LdapAuthenticationProvider(LdapTemplate ldapTemplate, NacosUserDetailsServiceImpl userDetailsService,
|
||||
NacosRoleServiceImpl nacosRoleService, String filterPrefix, boolean caseSensitive) {
|
||||
public LdapAuthenticationProvider(LdapTemplate ldapTemplate, NacosUserService userDetailsService,
|
||||
NacosRoleService nacosRoleService, String filterPrefix, boolean caseSensitive) {
|
||||
this.ldapTemplate = ldapTemplate;
|
||||
this.nacosRoleService = nacosRoleService;
|
||||
this.userDetailsService = userDetailsService;
|
||||
|
@ -94,7 +94,8 @@ public class LdapAuthenticationProvider implements AuthenticationProvider {
|
|||
try {
|
||||
userDetails = userDetailsService.loadUserByUsername(AuthConstants.LDAP_PREFIX + username);
|
||||
} catch (UsernameNotFoundException exception) {
|
||||
userDetailsService.createUser(AuthConstants.LDAP_PREFIX + username, AuthConstants.LDAP_DEFAULT_ENCODED_PASSWORD);
|
||||
userDetailsService.createUser(AuthConstants.LDAP_PREFIX + username,
|
||||
AuthConstants.LDAP_DEFAULT_ENCODED_PASSWORD, false);
|
||||
User user = new User();
|
||||
user.setUsername(AuthConstants.LDAP_PREFIX + username);
|
||||
user.setPassword(AuthConstants.LDAP_DEFAULT_ENCODED_PASSWORD);
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.roles;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Nacos abstract cached role service.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@Service
|
||||
public abstract class AbstractCachedRoleService implements NacosRoleService {
|
||||
|
||||
protected static final int DEFAULT_PAGE_NO = 1;
|
||||
|
||||
private volatile Set<String> roleSet = new ConcurrentHashSet<>();
|
||||
|
||||
private volatile Map<String, List<RoleInfo>> roleInfoMap = new ConcurrentHashMap<>();
|
||||
|
||||
private volatile Map<String, List<PermissionInfo>> permissionInfoMap = new ConcurrentHashMap<>();
|
||||
|
||||
protected Set<String> getCachedRoleSet() {
|
||||
return roleSet;
|
||||
}
|
||||
|
||||
protected Map<String, List<RoleInfo>> getCachedRoleInfoMap() {
|
||||
return roleInfoMap;
|
||||
}
|
||||
|
||||
protected Map<String, List<PermissionInfo>> getCachedPermissionInfoMap() {
|
||||
return permissionInfoMap;
|
||||
}
|
||||
|
||||
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
|
||||
protected void reload() {
|
||||
try {
|
||||
List<RoleInfo> roleInfoPage = getAllRoles();
|
||||
Set<String> tmpRoleSet = new HashSet<>(16);
|
||||
Map<String, List<RoleInfo>> tmpRoleInfoMap = new ConcurrentHashMap<>(16);
|
||||
for (RoleInfo roleInfo : roleInfoPage) {
|
||||
if (!tmpRoleInfoMap.containsKey(roleInfo.getUsername())) {
|
||||
tmpRoleInfoMap.put(roleInfo.getUsername(), new ArrayList<>());
|
||||
}
|
||||
tmpRoleInfoMap.get(roleInfo.getUsername()).add(roleInfo);
|
||||
tmpRoleSet.add(roleInfo.getRole());
|
||||
}
|
||||
|
||||
Map<String, List<PermissionInfo>> tmpPermissionInfoMap = new ConcurrentHashMap<>(16);
|
||||
for (String role : tmpRoleSet) {
|
||||
Page<PermissionInfo> permissionInfoPage = getPermissions(role, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
|
||||
tmpPermissionInfoMap.put(role, permissionInfoPage.getPageItems());
|
||||
}
|
||||
|
||||
roleSet = tmpRoleSet;
|
||||
roleInfoMap = tmpRoleInfoMap;
|
||||
permissionInfoMap = tmpPermissionInfoMap;
|
||||
} catch (Exception e) {
|
||||
Loggers.AUTH.warn("[LOAD-ROLES] load failed", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.roles;
|
||||
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.plugin.auth.api.Permission;
|
||||
import com.alibaba.nacos.plugin.auth.api.Resource;
|
||||
import com.alibaba.nacos.plugin.auth.constant.Constants;
|
||||
import com.alibaba.nacos.plugin.auth.constant.SignType;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.alibaba.nacos.api.common.Constants.DEFAULT_NAMESPACE_ID;
|
||||
|
||||
/**
|
||||
* Nacos abstract cached role service.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@Service
|
||||
public abstract class AbstractCheckedRoleService extends AbstractCachedRoleService implements NacosRoleService {
|
||||
|
||||
private final AuthConfigs authConfigs;
|
||||
|
||||
protected AbstractCheckedRoleService(AuthConfigs authConfigs) {
|
||||
this.authConfigs = authConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(NacosUser nacosUser, Permission permission) {
|
||||
if (isUpdatePasswordPermission(permission)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<RoleInfo> roleInfoList = getRoles(nacosUser.getUserName());
|
||||
if (CollectionUtils.isEmpty(roleInfoList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Global admin pass:
|
||||
for (RoleInfo roleInfo : roleInfoList) {
|
||||
if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole())) {
|
||||
nacosUser.setGlobalAdmin(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Old global admin can pass resource 'console/':
|
||||
if (permission.getResource().getName().startsWith(AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For other roles, use a pattern match to decide if pass or not.
|
||||
for (RoleInfo roleInfo : roleInfoList) {
|
||||
List<PermissionInfo> permissionInfoList = getPermissions(roleInfo.getRole());
|
||||
if (CollectionUtils.isEmpty(permissionInfoList)) {
|
||||
continue;
|
||||
}
|
||||
for (PermissionInfo permissionInfo : permissionInfoList) {
|
||||
String permissionResource = permissionInfo.getResource().replaceAll("\\*", ".*");
|
||||
String permissionAction = permissionInfo.getAction();
|
||||
if (permissionAction.contains(permission.getAction()) && Pattern.matches(permissionResource,
|
||||
joinResource(permission.getResource()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Boolean> isDuplicatePermission(String role, String resource, String action) {
|
||||
List<PermissionInfo> permissionInfos = getPermissions(role);
|
||||
if (CollectionUtils.isEmpty(permissionInfos)) {
|
||||
return Result.success(Boolean.FALSE);
|
||||
}
|
||||
for (PermissionInfo permissionInfo : permissionInfos) {
|
||||
boolean resourceMatch = StringUtils.equals(resource, permissionInfo.getResource());
|
||||
boolean actionMatch =
|
||||
StringUtils.equals(action, permissionInfo.getAction()) || "rw".equals(permissionInfo.getAction());
|
||||
if (resourceMatch && actionMatch) {
|
||||
return Result.success(Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
return Result.success(Boolean.FALSE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGlobalAdminRole(String userName) {
|
||||
List<RoleInfo> roles = getRoles(userName);
|
||||
return roles.stream().anyMatch(roleInfo -> AuthConstants.GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGlobalAdminRole() {
|
||||
if (authConfigs.isHasGlobalAdminRole()) {
|
||||
return true;
|
||||
}
|
||||
List<RoleInfo> roles = getAllRoles();
|
||||
boolean hasGlobalAdminRole = CollectionUtils.isNotEmpty(roles) && roles.stream()
|
||||
.anyMatch(roleInfo -> AuthConstants.GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole()));
|
||||
authConfigs.setHasGlobalAdminRole(hasGlobalAdminRole);
|
||||
return hasGlobalAdminRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* If API is update user password, don't do permission check, because there is permission check in API logic.
|
||||
*/
|
||||
private boolean isUpdatePasswordPermission(Permission permission) {
|
||||
Properties properties = permission.getResource().getProperties();
|
||||
return null != properties && properties.contains(AuthConstants.UPDATE_PASSWORD_ENTRY_POINT);
|
||||
}
|
||||
|
||||
private String joinResource(Resource resource) {
|
||||
if (SignType.SPECIFIED.equals(resource.getType())) {
|
||||
return resource.getName();
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
String namespaceId = resource.getNamespaceId();
|
||||
if (StringUtils.isNotBlank(namespaceId)) {
|
||||
// https://github.com/alibaba/nacos/issues/10347
|
||||
if (!DEFAULT_NAMESPACE_ID.equals(namespaceId)) {
|
||||
result.append(namespaceId);
|
||||
}
|
||||
}
|
||||
String group = resource.getGroup();
|
||||
if (StringUtils.isBlank(group)) {
|
||||
result.append(Constants.Resource.SPLITTER).append('*');
|
||||
} else {
|
||||
result.append(Constants.Resource.SPLITTER).append(group);
|
||||
}
|
||||
String resourceName = resource.getName();
|
||||
if (StringUtils.isBlank(resourceName)) {
|
||||
result.append(Constants.Resource.SPLITTER).append(resource.getType().toLowerCase()).append("/*");
|
||||
} else {
|
||||
result.append(Constants.Resource.SPLITTER).append(resource.getType().toLowerCase()).append('/')
|
||||
.append(resourceName);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.roles;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.plugin.auth.api.Permission;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Nacos auth plugin role service interface.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public interface NacosRoleService {
|
||||
|
||||
/**
|
||||
* Determine if the user has permission of the resource.
|
||||
*
|
||||
* <p>Note if the user has many roles, this method returns true if any one role of the user has the desired
|
||||
* permission.
|
||||
*
|
||||
* @param nacosUser user info
|
||||
* @param permission permission to auth
|
||||
* @return true if granted, false otherwise
|
||||
*/
|
||||
boolean hasPermission(NacosUser nacosUser, Permission permission);
|
||||
|
||||
/**
|
||||
* Add permission to tole.
|
||||
*
|
||||
* @param role role name
|
||||
* @param resource resource
|
||||
* @param action action
|
||||
*/
|
||||
void addPermission(String role, String resource, String action);
|
||||
|
||||
/**
|
||||
* Delete permission from role.
|
||||
*
|
||||
* @param role role name
|
||||
* @param resource resource
|
||||
* @param action action
|
||||
*/
|
||||
void deletePermission(String role, String resource, String action);
|
||||
|
||||
/**
|
||||
* Get all permissions of the role.
|
||||
*
|
||||
* @param role role name
|
||||
* @return List of {@link PermissionInfo} for the role
|
||||
*/
|
||||
List<PermissionInfo> getPermissions(String role);
|
||||
|
||||
/**
|
||||
* Accurate search permissions by role name pattern.
|
||||
*
|
||||
* @param role role name pattern
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @return List of {@link RoleInfo} match role name pattern
|
||||
*/
|
||||
Page<PermissionInfo> getPermissions(String role, int pageNo, int pageSize);
|
||||
|
||||
/**
|
||||
* Blur search permissions by role name pattern.
|
||||
*
|
||||
* @param role role name pattern
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @return List of {@link RoleInfo} match role name pattern
|
||||
*/
|
||||
Page<PermissionInfo> findPermissions(String role, int pageNo, int pageSize);
|
||||
|
||||
/**
|
||||
* Judge whether the permission is duplicate.
|
||||
*
|
||||
* @param role role name
|
||||
* @param resource resource
|
||||
* @param action action
|
||||
* @return true if duplicate, false otherwise
|
||||
*/
|
||||
Result<Boolean> isDuplicatePermission(String role, String resource, String action);
|
||||
|
||||
/**
|
||||
* Get All roles for target user.
|
||||
*
|
||||
* @param username username of target user
|
||||
* @return List of {@link RoleInfo} for target user
|
||||
*/
|
||||
List<RoleInfo> getRoles(String username);
|
||||
|
||||
/**
|
||||
* Accurate search roles by role name pattern.
|
||||
*
|
||||
* @param username username of target user
|
||||
* @param role role name
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @return List of {@link RoleInfo} match role name pattern
|
||||
*/
|
||||
Page<RoleInfo> getRoles(String username, String role, int pageNo, int pageSize);
|
||||
|
||||
/**
|
||||
* Blur search roles by role name pattern.
|
||||
*
|
||||
* @param username username of target user
|
||||
* @param role role name pattern
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @return List of {@link RoleInfo} match role name pattern
|
||||
*/
|
||||
Page<RoleInfo> findRoles(String username, String role, int pageNo, int pageSize);
|
||||
|
||||
/**
|
||||
* Blur search role names by role name pattern.
|
||||
*
|
||||
* @param role role name pattern
|
||||
* @return List of {@link RoleInfo} match role name pattern
|
||||
*/
|
||||
List<String> findRoleNames(String role);
|
||||
|
||||
/**
|
||||
* Get All roles in Nacos.
|
||||
*
|
||||
* @return List of {@link RoleInfo} in Nacos
|
||||
*/
|
||||
List<RoleInfo> getAllRoles();
|
||||
|
||||
/**
|
||||
* Add role to user.
|
||||
*
|
||||
* @param role role name
|
||||
* @param username user name
|
||||
*/
|
||||
void addRole(String role, String username);
|
||||
|
||||
/**
|
||||
* Delete Role from user.
|
||||
*
|
||||
* @param role role
|
||||
* @param userName userName
|
||||
*/
|
||||
void deleteRole(String role, String userName);
|
||||
|
||||
/**
|
||||
* Delete Role from Nacos.
|
||||
*
|
||||
* @param role role
|
||||
*/
|
||||
void deleteRole(String role);
|
||||
|
||||
/**
|
||||
* Add role.
|
||||
*
|
||||
* @param username user name
|
||||
*/
|
||||
void addAdminRole(String username);
|
||||
|
||||
/**
|
||||
* Check if user has admin role.
|
||||
*
|
||||
* @param userName user name
|
||||
* @return true if user has admin role.
|
||||
*/
|
||||
boolean hasGlobalAdminRole(String userName);
|
||||
|
||||
/**
|
||||
* Check if all user has at least one admin role.
|
||||
*
|
||||
* @return true if all user has at least one admin role.
|
||||
*/
|
||||
boolean hasGlobalAdminRole();
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.roles;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionPersistService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RolePersistService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Nacos builtin role service, implemented by directly access to database.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Service
|
||||
public class NacosRoleServiceDirectImpl extends AbstractCheckedRoleService implements NacosRoleService {
|
||||
|
||||
private static final int DEFAULT_PAGE_NO = 1;
|
||||
|
||||
private final AuthConfigs authConfigs;
|
||||
|
||||
private final RolePersistService rolePersistService;
|
||||
|
||||
private final NacosUserService userDetailsService;
|
||||
|
||||
private final PermissionPersistService permissionPersistService;
|
||||
|
||||
public NacosRoleServiceDirectImpl(AuthConfigs authConfigs, RolePersistService rolePersistService,
|
||||
NacosUserService userDetailsService, PermissionPersistService permissionPersistService) {
|
||||
super(authConfigs);
|
||||
this.authConfigs = authConfigs;
|
||||
this.rolePersistService = rolePersistService;
|
||||
this.userDetailsService = userDetailsService;
|
||||
this.permissionPersistService = permissionPersistService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoleInfo> getRoles(String username) {
|
||||
List<RoleInfo> roleInfoList = getCachedRoleInfoMap().get(username);
|
||||
if (!authConfigs.isCachingEnabled() || roleInfoList == null) {
|
||||
Page<RoleInfo> roleInfoPage = getRoles(username, StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
|
||||
if (roleInfoPage != null) {
|
||||
roleInfoList = roleInfoPage.getPageItems();
|
||||
if (!CollectionUtils.isEmpty(roleInfoList)) {
|
||||
getCachedRoleInfoMap().put(username, roleInfoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return roleInfoList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> getRoles(String username, String role, int pageNo, int pageSize) {
|
||||
Page<RoleInfo> roles = rolePersistService.getRolesByUserNameAndRoleName(username, role, pageNo, pageSize);
|
||||
if (roles == null) {
|
||||
return new Page<>();
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoleInfo> getAllRoles() {
|
||||
Page<RoleInfo> roleInfoPage = rolePersistService.getRolesByUserNameAndRoleName(StringUtils.EMPTY,
|
||||
StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
|
||||
if (roleInfoPage == null) {
|
||||
return null;
|
||||
}
|
||||
return roleInfoPage.getPageItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PermissionInfo> getPermissions(String role) {
|
||||
List<PermissionInfo> permissionInfoList = getCachedPermissionInfoMap().get(role);
|
||||
if (!authConfigs.isCachingEnabled() || permissionInfoList == null) {
|
||||
Page<PermissionInfo> permissionInfoPage = getPermissions(role, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
|
||||
if (permissionInfoPage != null) {
|
||||
permissionInfoList = permissionInfoPage.getPageItems();
|
||||
if (!CollectionUtils.isEmpty(permissionInfoList)) {
|
||||
getCachedPermissionInfoMap().put(role, permissionInfoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return permissionInfoList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> getPermissions(String role, int pageNo, int pageSize) {
|
||||
Page<PermissionInfo> pageInfo = permissionPersistService.getPermissions(role, pageNo, pageSize);
|
||||
if (pageInfo == null) {
|
||||
return new Page<>();
|
||||
}
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRole(String role, String username) {
|
||||
if (userDetailsService.getUser(username) == null) {
|
||||
throw new IllegalArgumentException("user '" + username + "' not found!");
|
||||
}
|
||||
|
||||
if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(role)) {
|
||||
throw new IllegalArgumentException(
|
||||
"role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' is not permitted to create!");
|
||||
}
|
||||
|
||||
if (isUserBoundToRole(role, username)) {
|
||||
throw new IllegalArgumentException("user '" + username + "' already bound to the role '" + role + "'!");
|
||||
}
|
||||
|
||||
rolePersistService.addRole(role, username);
|
||||
getCachedRoleSet().add(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdminRole(String username) {
|
||||
if (userDetailsService.getUser(username) == null) {
|
||||
throw new IllegalArgumentException("user '" + username + "' not found!");
|
||||
}
|
||||
if (hasGlobalAdminRole()) {
|
||||
throw new IllegalArgumentException("role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' already exist !");
|
||||
}
|
||||
|
||||
rolePersistService.addRole(AuthConstants.GLOBAL_ADMIN_ROLE, username);
|
||||
getCachedRoleSet().add(AuthConstants.GLOBAL_ADMIN_ROLE);
|
||||
authConfigs.setHasGlobalAdminRole(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRole(String role, String userName) {
|
||||
rolePersistService.deleteRole(role, userName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRole(String role) {
|
||||
rolePersistService.deleteRole(role);
|
||||
getCachedRoleInfoMap().remove(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermission(String role, String resource, String action) {
|
||||
if (!getCachedRoleSet().contains(role)) {
|
||||
throw new IllegalArgumentException("role " + role + " not found!");
|
||||
}
|
||||
permissionPersistService.addPermission(role, resource, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePermission(String role, String resource, String action) {
|
||||
permissionPersistService.deletePermission(role, resource, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> findRoles(String username, String role, int pageNo, int pageSize) {
|
||||
return rolePersistService.findRolesLike4Page(username, role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findRoleNames(String role) {
|
||||
return rolePersistService.findRolesLikeRoleName(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> findPermissions(String role, int pageNo, int pageSize) {
|
||||
return permissionPersistService.findPermissionsLike4Page(role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
boolean isUserBoundToRole(String role, String username) {
|
||||
Page<RoleInfo> roleInfoPage = rolePersistService.getRolesByUserNameAndRoleName(username, role, DEFAULT_PAGE_NO,
|
||||
1);
|
||||
if (roleInfoPage == null) {
|
||||
return false;
|
||||
}
|
||||
List<RoleInfo> roleInfos = roleInfoPage.getPageItems();
|
||||
return CollectionUtils.isNotEmpty(roleInfos) && roleInfos.stream()
|
||||
.anyMatch(roleInfo -> role.equals(roleInfo.getRole()));
|
||||
}
|
||||
}
|
|
@ -1,422 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.roles;
|
||||
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.plugin.auth.api.Permission;
|
||||
import com.alibaba.nacos.plugin.auth.api.Resource;
|
||||
import com.alibaba.nacos.plugin.auth.constant.Constants;
|
||||
import com.alibaba.nacos.plugin.auth.constant.SignType;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionPersistService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RolePersistService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.alibaba.nacos.api.common.Constants.DEFAULT_NAMESPACE_ID;
|
||||
|
||||
/**
|
||||
* Nacos builtin role service.
|
||||
*
|
||||
* @author nkorange
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Service
|
||||
public class NacosRoleServiceImpl {
|
||||
|
||||
private static final int DEFAULT_PAGE_NO = 1;
|
||||
|
||||
@Autowired
|
||||
private AuthConfigs authConfigs;
|
||||
|
||||
@Autowired
|
||||
private RolePersistService rolePersistService;
|
||||
|
||||
@Autowired
|
||||
private NacosUserDetailsServiceImpl userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private PermissionPersistService permissionPersistService;
|
||||
|
||||
private volatile Set<String> roleSet = new ConcurrentHashSet<>();
|
||||
|
||||
private volatile Map<String, List<RoleInfo>> roleInfoMap = new ConcurrentHashMap<>();
|
||||
|
||||
private volatile Map<String, List<PermissionInfo>> permissionInfoMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
|
||||
private void reload() {
|
||||
try {
|
||||
Page<RoleInfo> roleInfoPage = rolePersistService.getRolesByUserNameAndRoleName(StringUtils.EMPTY,
|
||||
StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
|
||||
if (roleInfoPage == null) {
|
||||
return;
|
||||
}
|
||||
Set<String> tmpRoleSet = new HashSet<>(16);
|
||||
Map<String, List<RoleInfo>> tmpRoleInfoMap = new ConcurrentHashMap<>(16);
|
||||
for (RoleInfo roleInfo : roleInfoPage.getPageItems()) {
|
||||
if (!tmpRoleInfoMap.containsKey(roleInfo.getUsername())) {
|
||||
tmpRoleInfoMap.put(roleInfo.getUsername(), new ArrayList<>());
|
||||
}
|
||||
tmpRoleInfoMap.get(roleInfo.getUsername()).add(roleInfo);
|
||||
tmpRoleSet.add(roleInfo.getRole());
|
||||
}
|
||||
|
||||
Map<String, List<PermissionInfo>> tmpPermissionInfoMap = new ConcurrentHashMap<>(16);
|
||||
for (String role : tmpRoleSet) {
|
||||
Page<PermissionInfo> permissionInfoPage = permissionPersistService.getPermissions(role, DEFAULT_PAGE_NO,
|
||||
Integer.MAX_VALUE);
|
||||
tmpPermissionInfoMap.put(role, permissionInfoPage.getPageItems());
|
||||
}
|
||||
|
||||
roleSet = tmpRoleSet;
|
||||
roleInfoMap = tmpRoleInfoMap;
|
||||
permissionInfoMap = tmpPermissionInfoMap;
|
||||
} catch (Exception e) {
|
||||
Loggers.AUTH.warn("[LOAD-ROLES] load failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user has permission of the resource.
|
||||
*
|
||||
* <p>Note if the user has many roles, this method returns true if any one role of the user has the desired
|
||||
* permission.
|
||||
*
|
||||
* @param nacosUser user info
|
||||
* @param permission permission to auth
|
||||
* @return true if granted, false otherwise
|
||||
*/
|
||||
public boolean hasPermission(NacosUser nacosUser, Permission permission) {
|
||||
if (isUpdatePasswordPermission(permission)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<RoleInfo> roleInfoList = getRoles(nacosUser.getUserName());
|
||||
if (CollectionUtils.isEmpty(roleInfoList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Global admin pass:
|
||||
for (RoleInfo roleInfo : roleInfoList) {
|
||||
if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole())) {
|
||||
nacosUser.setGlobalAdmin(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Old global admin can pass resource 'console/':
|
||||
if (permission.getResource().getName().startsWith(AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For other roles, use a pattern match to decide if pass or not.
|
||||
for (RoleInfo roleInfo : roleInfoList) {
|
||||
List<PermissionInfo> permissionInfoList = getPermissions(roleInfo.getRole());
|
||||
if (CollectionUtils.isEmpty(permissionInfoList)) {
|
||||
continue;
|
||||
}
|
||||
for (PermissionInfo permissionInfo : permissionInfoList) {
|
||||
String permissionResource = permissionInfo.getResource().replaceAll("\\*", ".*");
|
||||
String permissionAction = permissionInfo.getAction();
|
||||
if (permissionAction.contains(permission.getAction()) && Pattern.matches(permissionResource,
|
||||
joinResource(permission.getResource()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If API is update user password, don't do permission check, because there is permission check in API logic.
|
||||
*/
|
||||
private boolean isUpdatePasswordPermission(Permission permission) {
|
||||
Properties properties = permission.getResource().getProperties();
|
||||
return null != properties && properties.contains(AuthConstants.UPDATE_PASSWORD_ENTRY_POINT);
|
||||
}
|
||||
|
||||
public List<RoleInfo> getRoles(String username) {
|
||||
List<RoleInfo> roleInfoList = roleInfoMap.get(username);
|
||||
if (!authConfigs.isCachingEnabled() || roleInfoList == null) {
|
||||
Page<RoleInfo> roleInfoPage = getRolesFromDatabase(username, StringUtils.EMPTY, DEFAULT_PAGE_NO,
|
||||
Integer.MAX_VALUE);
|
||||
if (roleInfoPage != null) {
|
||||
roleInfoList = roleInfoPage.getPageItems();
|
||||
if (!CollectionUtils.isEmpty(roleInfoList)) {
|
||||
roleInfoMap.put(username, roleInfoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return roleInfoList;
|
||||
}
|
||||
|
||||
public List<RoleInfo> getAllRoles() {
|
||||
Page<RoleInfo> roleInfoPage = rolePersistService.getRolesByUserNameAndRoleName(StringUtils.EMPTY,
|
||||
StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
|
||||
if (roleInfoPage == null) {
|
||||
return null;
|
||||
}
|
||||
return roleInfoPage.getPageItems();
|
||||
}
|
||||
|
||||
public Page<RoleInfo> getRolesFromDatabase(String userName, String role, int pageNo, int pageSize) {
|
||||
Page<RoleInfo> roles = rolePersistService.getRolesByUserNameAndRoleName(userName, role, pageNo, pageSize);
|
||||
if (roles == null) {
|
||||
return new Page<>();
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
public List<PermissionInfo> getPermissions(String role) {
|
||||
List<PermissionInfo> permissionInfoList = permissionInfoMap.get(role);
|
||||
if (!authConfigs.isCachingEnabled() || permissionInfoList == null) {
|
||||
Page<PermissionInfo> permissionInfoPage = getPermissionsFromDatabase(role, DEFAULT_PAGE_NO,
|
||||
Integer.MAX_VALUE);
|
||||
if (permissionInfoPage != null) {
|
||||
permissionInfoList = permissionInfoPage.getPageItems();
|
||||
if (!CollectionUtils.isEmpty(permissionInfoList)) {
|
||||
permissionInfoMap.put(role, permissionInfoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return permissionInfoList;
|
||||
}
|
||||
|
||||
public Page<PermissionInfo> getPermissionsByRoleFromDatabase(String role, int pageNo, int pageSize) {
|
||||
return permissionPersistService.getPermissions(role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add role.
|
||||
*
|
||||
* @param role role name
|
||||
* @param username user name
|
||||
*/
|
||||
public void addRole(String role, String username) {
|
||||
if (userDetailsService.getUserFromDatabase(username) == null) {
|
||||
throw new IllegalArgumentException("user '" + username + "' not found!");
|
||||
}
|
||||
|
||||
if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(role)) {
|
||||
throw new IllegalArgumentException(
|
||||
"role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' is not permitted to create!");
|
||||
}
|
||||
|
||||
if (isUserBoundToRole(role, username)) {
|
||||
throw new IllegalArgumentException(
|
||||
"user '" + username + "' already bound to the role '" + role + "'!");
|
||||
}
|
||||
|
||||
rolePersistService.addRole(role, username);
|
||||
roleSet.add(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add role.
|
||||
*
|
||||
* @param username user name
|
||||
*/
|
||||
public void addAdminRole(String username) {
|
||||
if (userDetailsService.getUserFromDatabase(username) == null) {
|
||||
throw new IllegalArgumentException("user '" + username + "' not found!");
|
||||
}
|
||||
if (hasGlobalAdminRole()) {
|
||||
throw new IllegalArgumentException("role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' already exist !");
|
||||
}
|
||||
|
||||
rolePersistService.addRole(AuthConstants.GLOBAL_ADMIN_ROLE, username);
|
||||
roleSet.add(AuthConstants.GLOBAL_ADMIN_ROLE);
|
||||
authConfigs.setHasGlobalAdminRole(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete user Role.
|
||||
*
|
||||
* @param role role
|
||||
* @param userName userName
|
||||
*/
|
||||
public void deleteRole(String role, String userName) {
|
||||
rolePersistService.deleteRole(role, userName);
|
||||
}
|
||||
|
||||
/**
|
||||
* deleteRole.
|
||||
*
|
||||
* @param role role
|
||||
*/
|
||||
public void deleteRole(String role) {
|
||||
rolePersistService.deleteRole(role);
|
||||
roleSet.remove(role);
|
||||
}
|
||||
|
||||
public Page<PermissionInfo> getPermissionsFromDatabase(String role, int pageNo, int pageSize) {
|
||||
Page<PermissionInfo> pageInfo = permissionPersistService.getPermissions(role, pageNo, pageSize);
|
||||
if (pageInfo == null) {
|
||||
return new Page<>();
|
||||
}
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add permission.
|
||||
*
|
||||
* @param role role name
|
||||
* @param resource resource
|
||||
* @param action action
|
||||
*/
|
||||
public void addPermission(String role, String resource, String action) {
|
||||
if (!roleSet.contains(role)) {
|
||||
throw new IllegalArgumentException("role " + role + " not found!");
|
||||
}
|
||||
permissionPersistService.addPermission(role, resource, action);
|
||||
}
|
||||
|
||||
public void deletePermission(String role, String resource, String action) {
|
||||
permissionPersistService.deletePermission(role, resource, action);
|
||||
}
|
||||
|
||||
public List<String> findRolesLikeRoleName(String role) {
|
||||
return rolePersistService.findRolesLikeRoleName(role);
|
||||
}
|
||||
|
||||
private String joinResource(Resource resource) {
|
||||
if (SignType.SPECIFIED.equals(resource.getType())) {
|
||||
return resource.getName();
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
String namespaceId = resource.getNamespaceId();
|
||||
if (StringUtils.isNotBlank(namespaceId)) {
|
||||
// https://github.com/alibaba/nacos/issues/10347
|
||||
if (!DEFAULT_NAMESPACE_ID.equals(namespaceId)) {
|
||||
result.append(namespaceId);
|
||||
}
|
||||
}
|
||||
String group = resource.getGroup();
|
||||
if (StringUtils.isBlank(group)) {
|
||||
result.append(Constants.Resource.SPLITTER).append('*');
|
||||
} else {
|
||||
result.append(Constants.Resource.SPLITTER).append(group);
|
||||
}
|
||||
String resourceName = resource.getName();
|
||||
if (StringUtils.isBlank(resourceName)) {
|
||||
result.append(Constants.Resource.SPLITTER).append(resource.getType().toLowerCase()).append("/*");
|
||||
} else {
|
||||
result.append(Constants.Resource.SPLITTER).append(resource.getType().toLowerCase()).append('/')
|
||||
.append(resourceName);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public Page<RoleInfo> findRolesLike4Page(String username, String role, int pageNo, int pageSize) {
|
||||
return rolePersistService.findRolesLike4Page(username, role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
public Page<PermissionInfo> findPermissionsLike4Page(String role, int pageNo, int pageSize) {
|
||||
return permissionPersistService.findPermissionsLike4Page(role, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if user has admin role.
|
||||
*
|
||||
* @param userName user name
|
||||
* @return true if user has admin role.
|
||||
*/
|
||||
public boolean hasGlobalAdminRole(String userName) {
|
||||
List<RoleInfo> roles = getRoles(userName);
|
||||
|
||||
return roles.stream().anyMatch(roleInfo -> AuthConstants.GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole()));
|
||||
}
|
||||
|
||||
/**
|
||||
* check if all user has at least one admin role.
|
||||
*
|
||||
* @return true if all user has at least one admin role.
|
||||
*/
|
||||
public boolean hasGlobalAdminRole() {
|
||||
if (authConfigs.isHasGlobalAdminRole()) {
|
||||
return true;
|
||||
}
|
||||
List<RoleInfo> roles = getAllRoles();
|
||||
boolean hasGlobalAdminRole = CollectionUtils.isNotEmpty(roles) && roles.stream()
|
||||
.anyMatch(roleInfo -> AuthConstants.GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole()));
|
||||
authConfigs.setHasGlobalAdminRole(hasGlobalAdminRole);
|
||||
return hasGlobalAdminRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* judge whether the permission is duplicate.
|
||||
*
|
||||
* @param role role name
|
||||
* @param resource resource
|
||||
* @param action action
|
||||
* @return true if duplicate, false otherwise
|
||||
*/
|
||||
public Result<Boolean> isDuplicatePermission(String role, String resource, String action) {
|
||||
List<PermissionInfo> permissionInfos = getPermissions(role);
|
||||
if (CollectionUtils.isEmpty(permissionInfos)) {
|
||||
return Result.success(Boolean.FALSE);
|
||||
}
|
||||
for (PermissionInfo permissionInfo : permissionInfos) {
|
||||
boolean resourceMatch = StringUtils.equals(resource, permissionInfo.getResource());
|
||||
boolean actionMatch = StringUtils.equals(action, permissionInfo.getAction()) || "rw".equals(permissionInfo.getAction());
|
||||
if (resourceMatch && actionMatch) {
|
||||
return Result.success(Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
return Result.success(Boolean.FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* judge whether the user is already bound to the role.
|
||||
*
|
||||
* @param role role name
|
||||
* @param username user name
|
||||
* @return true if the user is already bound to the role.
|
||||
*/
|
||||
public boolean isUserBoundToRole(String role, String username) {
|
||||
Page<RoleInfo> roleInfoPage = rolePersistService.getRolesByUserNameAndRoleName(username,
|
||||
role, DEFAULT_PAGE_NO, 1);
|
||||
if (roleInfoPage == null) {
|
||||
return false;
|
||||
}
|
||||
List<RoleInfo> roleInfos = roleInfoPage.getPageItems();
|
||||
return CollectionUtils.isNotEmpty(roleInfos) && roleInfos.stream()
|
||||
.anyMatch(roleInfo -> role.equals(roleInfo.getRole()));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.roles;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.constant.RequestUrlConstants;
|
||||
import com.alibaba.nacos.common.http.DefaultHttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.RemoteServerUtil;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Nacos builtin role service, implemented by remote request to nacos server.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class NacosRoleServiceRemoteImpl extends AbstractCheckedRoleService implements NacosRoleService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NacosRoleServiceRemoteImpl.class);
|
||||
|
||||
private final NacosRestTemplate nacosRestTemplate;
|
||||
|
||||
private final AuthConfigs authConfigs;
|
||||
|
||||
public NacosRoleServiceRemoteImpl(AuthConfigs authConfigs) {
|
||||
super(authConfigs);
|
||||
this.authConfigs = authConfigs;
|
||||
this.nacosRestTemplate = new DefaultHttpClientFactory(LOGGER).createNacosRestTemplate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermission(String role, String resource, String action) {
|
||||
Map<String, String> body = Map.of("role", role, "resource", resource, "action", action);
|
||||
try {
|
||||
HttpRestResult<String> result = nacosRestTemplate.postForm(
|
||||
buildRemotePermissionUrlPath(AuthConstants.PERMISSION_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), null, body, String.class);
|
||||
RemoteServerUtil.singleCheckResult(result);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePermission(String role, String resource, String action) {
|
||||
Query query = Query.newInstance().addParam("role", role).addParam("resource", resource)
|
||||
.addParam("action", action);
|
||||
try {
|
||||
HttpRestResult<String> result = nacosRestTemplate.delete(
|
||||
buildRemotePermissionUrlPath(AuthConstants.PERMISSION_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(result);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PermissionInfo> getPermissions(String role) {
|
||||
if (getCachedPermissionInfoMap().containsKey(role)) {
|
||||
return getCachedPermissionInfoMap().get(role);
|
||||
}
|
||||
reload();
|
||||
return getCachedPermissionInfoMap().get(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> getPermissions(String role, int pageNo, int pageSize) {
|
||||
Query query = Query.newInstance().addParam("role", role).addParam("pageNo", pageNo)
|
||||
.addParam("pageSize", pageSize).addParam("search", "accurate");
|
||||
return getPermissionInfoPageFromRemote(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> findPermissions(String role, int pageNo, int pageSize) {
|
||||
Query query = Query.newInstance().addParam("role", role).addParam("pageNo", pageNo)
|
||||
.addParam("pageSize", pageSize).addParam("search", "blur");
|
||||
return getPermissionInfoPageFromRemote(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoleInfo> getRoles(String username) {
|
||||
if (getCachedRoleInfoMap().containsKey(username)) {
|
||||
return getCachedRoleInfoMap().get(username);
|
||||
}
|
||||
reload();
|
||||
return getCachedRoleInfoMap().get(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> getRoles(String username, String role, int pageNo, int pageSize) {
|
||||
Query query = Query.newInstance().addParam("username", username).addParam("role", role)
|
||||
.addParam("pageNo", pageNo).addParam("pageSize", pageSize).addParam("search", "accurate");
|
||||
return getRoleInfoPageFromRemote(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> findRoles(String username, String role, int pageNo, int pageSize) {
|
||||
Query query = Query.newInstance().addParam("username", username).addParam("role", role)
|
||||
.addParam("pageNo", pageNo).addParam("pageSize", pageSize).addParam("search", "blur");
|
||||
return getRoleInfoPageFromRemote(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findRoleNames(String role) {
|
||||
Query query = Query.newInstance().addParam("role", role);
|
||||
try {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.get(
|
||||
buildRemoteRoleUrlPath(AuthConstants.ROLE_PATH + "/search"),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(httpResult);
|
||||
Result<List<String>> result = JacksonUtils.toObj(httpResult.getData(), new TypeReference<>() {
|
||||
});
|
||||
return result.getData();
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoleInfo> getAllRoles() {
|
||||
return getRoles(StringUtils.EMPTY, StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE).getPageItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRole(String role, String username) {
|
||||
if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(role)) {
|
||||
throw new IllegalArgumentException(
|
||||
"role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' is not permitted to create!");
|
||||
}
|
||||
Map<String, String> body = Map.of("role", role, "username", username);
|
||||
try {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.postForm(
|
||||
buildRemoteRoleUrlPath(AuthConstants.ROLE_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), body, String.class);
|
||||
RemoteServerUtil.singleCheckResult(httpResult);
|
||||
getCachedRoleSet().add(role);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRole(String role, String userName) {
|
||||
Query query = Query.newInstance().addParam("role", role).addParam("userName", userName);
|
||||
try {
|
||||
HttpRestResult<String> result = nacosRestTemplate.delete(buildRemoteRoleUrlPath(AuthConstants.ROLE_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(result);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteRole(String role) {
|
||||
Query query = Query.newInstance().addParam("role", role);
|
||||
try {
|
||||
HttpRestResult<String> result = nacosRestTemplate.delete(buildRemoteRoleUrlPath(AuthConstants.ROLE_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(result);
|
||||
getCachedRoleSet().remove(role);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdminRole(String username) {
|
||||
if (hasGlobalAdminRole()) {
|
||||
throw new IllegalArgumentException("role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' already exist !");
|
||||
}
|
||||
addRole(AuthConstants.GLOBAL_ADMIN_ROLE, username);
|
||||
getCachedRoleSet().add(AuthConstants.GLOBAL_ADMIN_ROLE);
|
||||
authConfigs.setHasGlobalAdminRole(true);
|
||||
}
|
||||
|
||||
private String buildRemotePermissionUrlPath(String apiPath) {
|
||||
return RequestUrlConstants.HTTP_PREFIX + RemoteServerUtil.getOneNacosServerAddress()
|
||||
+ RemoteServerUtil.getRemoteServerContextPath() + apiPath;
|
||||
}
|
||||
|
||||
private Page<PermissionInfo> getPermissionInfoPageFromRemote(Query query) {
|
||||
try {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.get(
|
||||
buildRemotePermissionUrlPath(AuthConstants.PERMISSION_PATH + "/list"),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(httpResult);
|
||||
Result<Page<PermissionInfo>> result = JacksonUtils.toObj(httpResult.getData(), new TypeReference<>() {
|
||||
});
|
||||
return result.getData();
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String buildRemoteRoleUrlPath(String apiPath) {
|
||||
return RequestUrlConstants.HTTP_PREFIX + RemoteServerUtil.getOneNacosServerAddress()
|
||||
+ RemoteServerUtil.getRemoteServerContextPath() + apiPath;
|
||||
}
|
||||
|
||||
private Page<RoleInfo> getRoleInfoPageFromRemote(Query query) {
|
||||
try {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.get(
|
||||
buildRemoteRoleUrlPath(AuthConstants.ROLE_PATH + "/list"),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(httpResult);
|
||||
Result<Page<RoleInfo>> result = JacksonUtils.toObj(httpResult.getData(), new TypeReference<>() {
|
||||
});
|
||||
return result.getData();
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.users;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Nacos abstract cached user service.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@Service
|
||||
public abstract class AbstractCachedUserService implements NacosUserService {
|
||||
|
||||
private Map<String, User> userMap = new ConcurrentHashMap<>();
|
||||
|
||||
protected AbstractCachedUserService() {
|
||||
}
|
||||
|
||||
protected Map<String, User> getCachedUserMap() {
|
||||
return userMap;
|
||||
}
|
||||
|
||||
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
|
||||
protected void reload() {
|
||||
try {
|
||||
Page<User> users = getUsers(1, Integer.MAX_VALUE, StringUtils.EMPTY);
|
||||
if (users == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, User> map = new ConcurrentHashMap<>(16);
|
||||
for (User user : users.getPageItems()) {
|
||||
map.put(user.getUsername(), user);
|
||||
}
|
||||
userMap = map;
|
||||
} catch (Exception e) {
|
||||
Loggers.AUTH.warn("[LOAD-USERS] load failed", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.users;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Nacos auth plugin user service interface.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public interface NacosUserService extends UserDetailsService {
|
||||
|
||||
/**
|
||||
* Update user password.
|
||||
*
|
||||
* @param username username to be updated password
|
||||
* @param password new password
|
||||
*/
|
||||
void updateUserPassword(String username, String password);
|
||||
|
||||
/**
|
||||
* Get users by paged.
|
||||
*
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @param username username
|
||||
* @return user list
|
||||
*/
|
||||
Page<User> getUsers(int pageNo, int pageSize, String username);
|
||||
|
||||
/**
|
||||
* Find users with blur search by paged.
|
||||
*
|
||||
* @param username username
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @return user list
|
||||
*/
|
||||
Page<User> findUsers(String username, int pageNo, int pageSize);
|
||||
|
||||
/**
|
||||
* Get User info by username.
|
||||
*
|
||||
* @param username username
|
||||
* @return {@link User} information
|
||||
*/
|
||||
User getUser(String username);
|
||||
|
||||
/**
|
||||
* Find usernames with blur search.
|
||||
*
|
||||
* @param username username
|
||||
* @return usernames
|
||||
*/
|
||||
List<String> findUserNames(String username);
|
||||
|
||||
/**
|
||||
* Create user.
|
||||
*
|
||||
* @param username username
|
||||
* @param password password
|
||||
*/
|
||||
default void createUser(String username, String password) {
|
||||
createUser(username, password, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create user.
|
||||
*
|
||||
* @param username username
|
||||
* @param password password
|
||||
* @param encode {@code true} will encode password, {@code false} will not encode password
|
||||
*/
|
||||
void createUser(String username, String password, boolean encode);
|
||||
|
||||
/**
|
||||
* Delete user.
|
||||
*
|
||||
* @param username username
|
||||
*/
|
||||
void deleteUser(String username);
|
||||
}
|
|
@ -16,109 +16,83 @@
|
|||
|
||||
package com.alibaba.nacos.plugin.auth.impl.users;
|
||||
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.UserPersistService;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.UserPersistService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Custom user service.
|
||||
* Custom user service, implemented by directly access to database.
|
||||
*
|
||||
* @author wfnuser
|
||||
* @author nkorange
|
||||
*/
|
||||
@Service
|
||||
public class NacosUserDetailsServiceImpl implements UserDetailsService {
|
||||
public class NacosUserServiceDirectImpl extends AbstractCachedUserService implements NacosUserService {
|
||||
|
||||
private Map<String, User> userMap = new ConcurrentHashMap<>();
|
||||
private final UserPersistService userPersistService;
|
||||
|
||||
@Autowired
|
||||
private UserPersistService userPersistService;
|
||||
private final AuthConfigs authConfigs;
|
||||
|
||||
@Autowired
|
||||
private AuthConfigs authConfigs;
|
||||
|
||||
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
|
||||
private void reload() {
|
||||
try {
|
||||
Page<User> users = getUsersFromDatabase(1, Integer.MAX_VALUE, StringUtils.EMPTY);
|
||||
if (users == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, User> map = new ConcurrentHashMap<>(16);
|
||||
for (User user : users.getPageItems()) {
|
||||
map.put(user.getUsername(), user);
|
||||
}
|
||||
userMap = map;
|
||||
} catch (Exception e) {
|
||||
Loggers.AUTH.warn("[LOAD-USERS] load failed", e);
|
||||
}
|
||||
public NacosUserServiceDirectImpl(AuthConfigs authConfigs, UserPersistService userPersistService) {
|
||||
super();
|
||||
this.userPersistService = userPersistService;
|
||||
this.authConfigs = authConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
|
||||
User user = userMap.get(username);
|
||||
User user = getCachedUserMap().get(username);
|
||||
if (!authConfigs.isCachingEnabled()) {
|
||||
user = userPersistService.findUserByUsername(username);
|
||||
user = getUser(username);
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException(String.format("User %s not found", username));
|
||||
}
|
||||
return new NacosUserDetails(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserPassword(String username, String password) {
|
||||
userPersistService.updateUserPassword(username, password);
|
||||
userPersistService.updateUserPassword(username, PasswordEncoderUtil.encode(password));
|
||||
}
|
||||
|
||||
public Page<User> getUsersFromDatabase(int pageNo, int pageSize, String username) {
|
||||
@Override
|
||||
public Page<User> getUsers(int pageNo, int pageSize, String username) {
|
||||
return userPersistService.getUsers(pageNo, pageSize, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser(String username) {
|
||||
User user = userMap.get(username);
|
||||
if (!authConfigs.isCachingEnabled() || user == null) {
|
||||
user = getUserFromDatabase(username);
|
||||
if (user != null) {
|
||||
userMap.put(username, user);
|
||||
}
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
public User getUserFromDatabase(String username) {
|
||||
return userPersistService.findUserByUsername(username);
|
||||
}
|
||||
|
||||
public List<String> findUserLikeUsername(String username) {
|
||||
@Override
|
||||
public List<String> findUserNames(String username) {
|
||||
return userPersistService.findUserLikeUsername(username);
|
||||
}
|
||||
|
||||
public void createUser(String username, String password) {
|
||||
@Override
|
||||
public void createUser(String username, String password, boolean encode) {
|
||||
if (encode) {
|
||||
password = PasswordEncoderUtil.encode(password);
|
||||
}
|
||||
userPersistService.createUser(username, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUser(String username) {
|
||||
userPersistService.deleteUser(username);
|
||||
}
|
||||
|
||||
public Page<User> findUsersLike4Page(String username, int pageNo, int pageSize) {
|
||||
@Override
|
||||
public Page<User> findUsers(String username, int pageNo, int pageSize) {
|
||||
return userPersistService.findUsersLike4Page(username, pageNo, pageSize);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.users;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.constant.RequestUrlConstants;
|
||||
import com.alibaba.nacos.common.http.DefaultHttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.RemoteServerUtil;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Custom user service, implemented by remote request to nacos server.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class NacosUserServiceRemoteImpl extends AbstractCachedUserService implements NacosUserService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NacosUserServiceRemoteImpl.class);
|
||||
|
||||
private final NacosRestTemplate nacosRestTemplate;
|
||||
|
||||
private final AuthConfigs authConfigs;
|
||||
|
||||
public NacosUserServiceRemoteImpl(AuthConfigs authConfigs) {
|
||||
super();
|
||||
this.authConfigs = authConfigs;
|
||||
this.nacosRestTemplate = new DefaultHttpClientFactory(LOGGER).createNacosRestTemplate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
User user = getUser(username);
|
||||
if (null == user) {
|
||||
throw new UsernameNotFoundException(String.format("User %s not found", username));
|
||||
}
|
||||
return new NacosUserDetails(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserPassword(String username, String password) {
|
||||
Query query = Query.newInstance().addParam("username", username);
|
||||
Map<String, String> body = Map.of("newPassword", password);
|
||||
try {
|
||||
HttpRestResult<String> result = nacosRestTemplate.putForm(buildRemoteUserUrlPath(AuthConstants.USER_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, body, String.class);
|
||||
RemoteServerUtil.singleCheckResult(result);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<User> getUsers(int pageNo, int pageSize, String username) {
|
||||
Query query = Query.newInstance().addParam("username", username).addParam("pageNo", pageNo)
|
||||
.addParam("pageSize", pageSize).addParam("search", "accurate");
|
||||
return getUserPageFromRemote(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<User> findUsers(String username, int pageNo, int pageSize) {
|
||||
Query query = Query.newInstance().addParam("username", username).addParam("pageNo", pageNo)
|
||||
.addParam("pageSize", pageSize).addParam("search", "blur");
|
||||
return getUserPageFromRemote(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser(String username) {
|
||||
if (getCachedUserMap().containsKey(username)) {
|
||||
return getCachedUserMap().get(username);
|
||||
}
|
||||
reload();
|
||||
return getCachedUserMap().get(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findUserNames(String username) {
|
||||
Query query = Query.newInstance().addParam("username", username);
|
||||
try {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.get(
|
||||
buildRemoteUserUrlPath(AuthConstants.USER_PATH + "/search"),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(httpResult);
|
||||
Result<List<String>> result = JacksonUtils.toObj(httpResult.getData(), new TypeReference<>() {
|
||||
});
|
||||
return result.getData();
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createUser(String username, String password, boolean encode) {
|
||||
// ignore encode = true, let nacos server do encode
|
||||
Query query = Query.newInstance().addParam("username", username);
|
||||
Map<String, String> body = Map.of("password", password);
|
||||
try {
|
||||
HttpRestResult<String> result = nacosRestTemplate.postForm(buildRemoteUserUrlPath(AuthConstants.USER_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, body, String.class);
|
||||
RemoteServerUtil.singleCheckResult(result);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUser(String username) {
|
||||
Query query = Query.newInstance().addParam("username", username);
|
||||
try {
|
||||
HttpRestResult<String> result = nacosRestTemplate.delete(buildRemoteUserUrlPath(AuthConstants.USER_PATH),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(result);
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String buildRemoteUserUrlPath(String apiPath) {
|
||||
return RequestUrlConstants.HTTP_PREFIX + RemoteServerUtil.getOneNacosServerAddress()
|
||||
+ RemoteServerUtil.getRemoteServerContextPath() + apiPath;
|
||||
}
|
||||
|
||||
private Page<User> getUserPageFromRemote(Query query) {
|
||||
try {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.get(
|
||||
buildRemoteUserUrlPath(AuthConstants.USER_PATH + "/list"),
|
||||
RemoteServerUtil.buildServerRemoteHeader(authConfigs), query, String.class);
|
||||
RemoteServerUtil.singleCheckResult(httpResult);
|
||||
Result<Page<User>> result = JacksonUtils.toObj(httpResult.getData(), new TypeReference<>() {
|
||||
});
|
||||
return result.getData();
|
||||
} catch (NacosException e) {
|
||||
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
|
||||
} catch (Exception unpectedException) {
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, unpectedException.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright 1999-2025 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.utils;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.auth.config.AuthConfigs;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||
import com.alibaba.nacos.sys.file.FileChangeEvent;
|
||||
import com.alibaba.nacos.sys.file.FileWatcher;
|
||||
import com.alibaba.nacos.sys.file.WatchFileCenter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Nacos auth plugin remote nacos server util.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class RemoteServerUtil {
|
||||
|
||||
private static List<String> serverAddresses = new LinkedList<>();
|
||||
|
||||
private static AtomicInteger index = new AtomicInteger();
|
||||
|
||||
private static String remoteServerContextPath = "/nacos";
|
||||
|
||||
static {
|
||||
readRemoteServerAddress();
|
||||
registerWatcher();
|
||||
initRemoteServerContextPath();
|
||||
}
|
||||
|
||||
private static void initRemoteServerContextPath() {
|
||||
remoteServerContextPath = EnvUtil.getProperty("nacos.console.remote.server.context-path", "/nacos");
|
||||
}
|
||||
|
||||
private static void registerWatcher() {
|
||||
try {
|
||||
WatchFileCenter.registerWatcher(EnvUtil.getClusterConfFilePath(), new FileWatcher() {
|
||||
|
||||
@Override
|
||||
public void onChange(FileChangeEvent event) {
|
||||
readRemoteServerAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interest(String context) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read nacos server address from cluster.conf.
|
||||
*/
|
||||
public static void readRemoteServerAddress() {
|
||||
try {
|
||||
serverAddresses = EnvUtil.readClusterConf();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getServerAddresses() {
|
||||
return new LinkedList<>(serverAddresses);
|
||||
}
|
||||
|
||||
public static String getOneNacosServerAddress() {
|
||||
int actual = index.getAndUpdate(operand -> (operand + 1) % serverAddresses.size());
|
||||
return serverAddresses.get(actual);
|
||||
}
|
||||
|
||||
public static String getRemoteServerContextPath() {
|
||||
return remoteServerContextPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Single check http result, if not success, wrapper result as Nacos exception.
|
||||
*
|
||||
* @param result http execute result
|
||||
* @throws NacosException wrapper result as NacosException
|
||||
*/
|
||||
public static void singleCheckResult(HttpRestResult<String> result) throws NacosException {
|
||||
if (result.ok()) {
|
||||
return;
|
||||
}
|
||||
throw new NacosException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* According input {@link AuthConfigs} to build remote server identity header.
|
||||
*
|
||||
* @param authConfigs authConfigs
|
||||
* @return remote server identity header
|
||||
*/
|
||||
public static Header buildServerRemoteHeader(AuthConfigs authConfigs) {
|
||||
Header header = Header.newInstance();
|
||||
if (StringUtils.isNotBlank(authConfigs.getServerIdentityKey())) {
|
||||
header.addParam(authConfigs.getServerIdentityKey(), authConfigs.getServerIdentityValue());
|
||||
}
|
||||
return header;
|
||||
}
|
||||
}
|
|
@ -21,11 +21,11 @@ import com.alibaba.nacos.plugin.auth.api.Permission;
|
|||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetails;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -48,13 +48,13 @@ public class AbstractAuthenticationManagerTest {
|
|||
private AbstractAuthenticationManager abstractAuthenticationManager;
|
||||
|
||||
@Mock
|
||||
private NacosUserDetailsServiceImpl userDetailsService;
|
||||
private NacosUserService userDetailsService;
|
||||
|
||||
@Mock
|
||||
private TokenManagerDelegate jwtTokenManager;
|
||||
|
||||
@Mock
|
||||
private NacosRoleServiceImpl roleService;
|
||||
private NacosRoleService roleService;
|
||||
|
||||
private User user;
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ package com.alibaba.nacos.plugin.auth.impl.authenticate;
|
|||
|
||||
import com.alibaba.nacos.plugin.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.User;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetails;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.users.NacosUserService;
|
||||
import com.alibaba.nacos.plugin.auth.impl.utils.PasswordEncoderUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -39,13 +39,13 @@ import static org.mockito.Mockito.when;
|
|||
public class LdapAuthenticationManagerTest {
|
||||
|
||||
@Mock
|
||||
private NacosUserDetailsServiceImpl userDetailsService;
|
||||
private NacosUserService userDetailsService;
|
||||
|
||||
@Mock
|
||||
private TokenManagerDelegate jwtTokenManager;
|
||||
|
||||
@Mock
|
||||
private NacosRoleServiceImpl roleService;
|
||||
private NacosRoleService roleService;
|
||||
|
||||
@Mock
|
||||
private LdapTemplate ldapTemplate;
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package com.alibaba.nacos.plugin.auth.impl.controller;
|
||||
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.api.model.v2.Result;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.api.model.Page;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
@ -42,7 +42,7 @@ public class PermissionControllerTest {
|
|||
private PermissionController permissionController;
|
||||
|
||||
@Mock
|
||||
private NacosRoleServiceImpl nacosRoleService;
|
||||
private NacosRoleService nacosRoleService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
|
@ -53,8 +53,7 @@ public class PermissionControllerTest {
|
|||
void testGetPermissions() {
|
||||
Page<PermissionInfo> permissionInfoPage = new Page<PermissionInfo>();
|
||||
|
||||
when(nacosRoleService.getPermissionsFromDatabase(anyString(), anyInt(), anyInt())).thenReturn(
|
||||
permissionInfoPage);
|
||||
when(nacosRoleService.getPermissions(anyString(), anyInt(), anyInt())).thenReturn(permissionInfoPage);
|
||||
|
||||
Object permissions = permissionController.getPermissions(1, 10, "admin");
|
||||
assertEquals(permissionInfoPage, permissions);
|
||||
|
@ -64,7 +63,7 @@ public class PermissionControllerTest {
|
|||
void testFuzzySearchPermission() {
|
||||
Page<PermissionInfo> permissionInfoPage = new Page<PermissionInfo>();
|
||||
|
||||
when(nacosRoleService.findPermissionsLike4Page(anyString(), anyInt(), anyInt())).thenReturn(permissionInfoPage);
|
||||
when(nacosRoleService.findPermissions(anyString(), anyInt(), anyInt())).thenReturn(permissionInfoPage);
|
||||
|
||||
Page<PermissionInfo> permissions = permissionController.fuzzySearchPermission(1, 10, "admin");
|
||||
assertEquals(permissionInfoPage, permissions);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue