Merge branch 'develop' of https://github.com/alibaba/nacos into jraft_naming
This commit is contained in:
commit
f5971e9a17
@ -19,7 +19,7 @@
|
||||
<parent>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.address.auth;
|
||||
|
||||
import com.alibaba.nacos.auth.AuthManager;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.model.Permission;
|
||||
import com.alibaba.nacos.auth.model.User;
|
||||
|
||||
/**
|
||||
* Address server auth manager.
|
||||
*
|
||||
* <p>For #3091, Only implement an empty auth manager so that address server can startup.</p>
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class AddressServerAuthManager implements AuthManager {
|
||||
|
||||
@Override
|
||||
public User login(Object request) throws AccessException {
|
||||
User result = new User();
|
||||
result.setUserName("nacos");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void auth(Permission permission, User user) throws AccessException {
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.address.configuration;
|
||||
|
||||
import com.alibaba.nacos.address.auth.AddressServerAuthManager;
|
||||
import com.alibaba.nacos.auth.AuthManager;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Address server spring configuration.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
@Configuration
|
||||
public class AddressServerSpringConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = AuthManager.class)
|
||||
public AuthManager getAuthManager() {
|
||||
return new AddressServerAuthManager();
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
83
auth/pom.xml
Normal file
83
auth/pom.xml
Normal file
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>nacos-auth</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>nacos-auth ${project.version}</name>
|
||||
<url>http://nacos.io</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>nacos-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -14,12 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth;
|
||||
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.model.Permission;
|
||||
import com.alibaba.nacos.auth.model.User;
|
||||
|
||||
/**
|
||||
* Access control entry. Can be extended by 3rd party implementations.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface AuthManager {
|
@ -14,8 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.annotation;
|
||||
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.auth.parser.DefaultResourceParser;
|
||||
import com.alibaba.nacos.auth.parser.ResourceParser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@ -25,6 +28,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* Annotation indicating that the annotated request should be authorized.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.common;
|
||||
|
||||
/**
|
||||
* Resource action type definitions.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public enum ActionTypes {
|
@ -14,18 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.common;
|
||||
|
||||
import com.alibaba.nacos.auth.common.env.ReloadableConfigs;
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.core.env.ReloadableConfigs;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -33,9 +31,9 @@ import java.util.Objects;
|
||||
* Auth related configurations.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Component
|
||||
@Configuration
|
||||
public class AuthConfigs {
|
||||
|
||||
@ -51,6 +49,11 @@ public class AuthConfigs {
|
||||
@Value("${nacos.core.auth.default.token.secret.key:}")
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* secret key byte array.
|
||||
*/
|
||||
private byte[] secretKeyBytes;
|
||||
|
||||
/**
|
||||
* Token validity time(seconds).
|
||||
*/
|
||||
@ -63,8 +66,11 @@ public class AuthConfigs {
|
||||
@Value("${nacos.core.auth.system.type:}")
|
||||
private String nacosAuthSystemType;
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
public byte[] getSecretKeyBytes() {
|
||||
if (secretKeyBytes == null) {
|
||||
secretKeyBytes = Decoders.BASE64.decode(secretKey);
|
||||
}
|
||||
return secretKeyBytes;
|
||||
}
|
||||
|
||||
public long getTokenValidityInSeconds() {
|
||||
@ -107,21 +113,4 @@ public class AuthConfigs {
|
||||
public static void setCachingEnabled(boolean cachingEnabled) {
|
||||
AuthConfigs.cachingEnabled = cachingEnabled;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean authFilterRegistration() {
|
||||
FilterRegistrationBean<AuthFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(authFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("authFilter");
|
||||
registration.setOrder(6);
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthFilter authFilter() {
|
||||
return new AuthFilter();
|
||||
}
|
||||
|
||||
}
|
@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.common;
|
||||
|
||||
/**
|
||||
* Types of all auth implementations.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public enum AuthSystemTypes {
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.env;
|
||||
package com.alibaba.nacos.auth.common.env;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -31,6 +31,7 @@ import java.util.Properties;
|
||||
* Reload application.properties.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Component
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.exception;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
|
||||
@ -22,6 +22,7 @@ import com.alibaba.nacos.api.exception.NacosException;
|
||||
* Exception to be thrown if authorization is failed.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class AccessException extends NacosException {
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -22,6 +22,7 @@ import java.io.Serializable;
|
||||
* Permission to auth.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class Permission implements Serializable {
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -22,6 +22,7 @@ import java.io.Serializable;
|
||||
* Resource used in authorization.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class Resource implements Serializable {
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -22,6 +22,7 @@ import java.io.Serializable;
|
||||
* User information in authorization.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class User implements Serializable {
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.parser;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
* Default resource parser.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class DefaultResourceParser implements ResourceParser {
|
@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.core.auth;
|
||||
package com.alibaba.nacos.auth.parser;
|
||||
|
||||
/**
|
||||
* Resource parser.
|
||||
*
|
||||
* @author nkorange
|
||||
* @author mai.jh
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface ResourceParser {
|
@ -19,7 +19,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -32,6 +32,7 @@ import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import com.alibaba.nacos.client.utils.TenantUtil;
|
||||
import com.alibaba.nacos.common.http.HttpRestResult;
|
||||
import com.alibaba.nacos.common.lifecycle.Closeable;
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
@ -165,6 +166,7 @@ public class ClientWorker implements Closeable {
|
||||
copy.remove(groupKey);
|
||||
cacheMap.set(copy);
|
||||
}
|
||||
reMakeCacheDataTaskId();
|
||||
LOGGER.info("[{}] [unsubscribe] {}", this.agent.getName(), groupKey);
|
||||
|
||||
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
|
||||
@ -177,11 +179,38 @@ public class ClientWorker implements Closeable {
|
||||
copy.remove(groupKey);
|
||||
cacheMap.set(copy);
|
||||
}
|
||||
reMakeCacheDataTaskId();
|
||||
LOGGER.info("[{}] [unsubscribe] {}", agent.getName(), groupKey);
|
||||
|
||||
MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remake cacheData taskId.
|
||||
*/
|
||||
private void reMakeCacheDataTaskId() {
|
||||
int listenerSize = cacheMap.get().size();
|
||||
int remakeTaskId = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
|
||||
if (remakeTaskId < (int) currentLongingTaskCount) {
|
||||
for (int i = 0; i < remakeTaskId; i++) {
|
||||
int count = 0;
|
||||
for (String key : cacheMap.get().keySet()) {
|
||||
if (count == ParamUtil.getPerTaskConfigSize()) {
|
||||
break;
|
||||
}
|
||||
CacheData cacheData = cacheMap.get().get(key);
|
||||
cacheData.setTaskId(i);
|
||||
synchronized (cacheMap) {
|
||||
Map<String, CacheData> copy = new HashMap<String, CacheData>(this.cacheMap.get());
|
||||
copy.put(key, cacheData);
|
||||
cacheMap.set(copy);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add cache data if absent.
|
||||
*
|
||||
@ -248,6 +277,8 @@ public class ClientWorker implements Closeable {
|
||||
cache.setInitializing(true);
|
||||
} else {
|
||||
cache = new CacheData(configFilterChainManager, agent.getName(), dataId, group, tenant);
|
||||
int taskId = cacheMap.get().size() / (int) ParamUtil.getPerTaskConfigSize();
|
||||
cache.setTaskId(taskId);
|
||||
// fix issue # 1317
|
||||
if (enableRemoteSyncConfig) {
|
||||
String[] ct = getServerConfig(dataId, group, tenant, 3000L);
|
||||
@ -394,11 +425,16 @@ public class ClientWorker implements Closeable {
|
||||
int longingTaskCount = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
|
||||
if (longingTaskCount > currentLongingTaskCount) {
|
||||
for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
|
||||
taskIdSet.add(i);
|
||||
// The task list is no order.So it maybe has issues when changing.
|
||||
executorService.execute(new LongPollingRunnable(i));
|
||||
}
|
||||
currentLongingTaskCount = longingTaskCount;
|
||||
} else if (longingTaskCount < currentLongingTaskCount) {
|
||||
for (int i = longingTaskCount; i < (int) currentLongingTaskCount; i++) {
|
||||
taskIdSet.remove(i);
|
||||
}
|
||||
}
|
||||
currentLongingTaskCount = longingTaskCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -656,7 +692,9 @@ public class ClientWorker implements Closeable {
|
||||
}
|
||||
inInitializingCacheList.clear();
|
||||
|
||||
executorService.execute(this);
|
||||
if (taskIdSet.contains(taskId)) {
|
||||
executorService.execute(this);
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
|
||||
@ -685,6 +723,11 @@ public class ClientWorker implements Closeable {
|
||||
private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>(
|
||||
new HashMap<String, CacheData>());
|
||||
|
||||
/**
|
||||
* Store the running taskId.
|
||||
*/
|
||||
private final ConcurrentHashSet<Integer> taskIdSet = new ConcurrentHashSet<Integer>();
|
||||
|
||||
private final HttpAgent agent;
|
||||
|
||||
private final ConfigFilterChainManager configFilterChainManager;
|
||||
|
@ -346,7 +346,7 @@ public class ServerListManager implements Closeable {
|
||||
private List<String> getApacheServerList(String url, String name) {
|
||||
try {
|
||||
HttpRestResult<String> httpResult = nacosRestTemplate.get(url, Header.EMPTY, Query.EMPTY, String.class);
|
||||
|
||||
|
||||
if (httpResult.ok()) {
|
||||
if (DEFAULT_NAME.equals(name)) {
|
||||
EnvUtil.setSelfEnv(httpResult.getHeader().getOriginalResponseHeader());
|
||||
@ -367,7 +367,7 @@ public class ServerListManager implements Closeable {
|
||||
return result;
|
||||
} else {
|
||||
LOGGER.error("[check-serverlist] error. addressServerUrl: {}, code: {}", addressServerUrl,
|
||||
httpResult.getCode());
|
||||
httpResult.getCode());
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -20,6 +20,7 @@ import com.alibaba.nacos.api.NacosFactory;
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
import com.alibaba.nacos.api.config.listener.AbstractListener;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
@ -28,7 +29,7 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@Ignore
|
||||
public class ConfigTest {
|
||||
@ -36,7 +37,7 @@ public class ConfigTest {
|
||||
private static ConfigService configService;
|
||||
|
||||
@Before
|
||||
public static void before() throws Exception {
|
||||
public void before() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
|
||||
configService = NacosFactory.createConfigService(properties);
|
||||
@ -48,7 +49,8 @@ public class ConfigTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void test() throws Exception {
|
||||
public void test() throws Exception {
|
||||
// set config
|
||||
final String dataId = "lessspring";
|
||||
final String group = "lessspring";
|
||||
final String content = "lessspring-" + System.currentTimeMillis();
|
||||
@ -57,24 +59,46 @@ public class ConfigTest {
|
||||
|
||||
ThreadUtils.sleep(10000L);
|
||||
|
||||
// set change listener
|
||||
final AtomicBoolean hasListener = new AtomicBoolean(false);
|
||||
final AtomicBoolean hasChangedCallback = new AtomicBoolean(false);
|
||||
final String[] changedTmpContent = {""};
|
||||
String response = configService.getConfigAndSignListener(dataId, group, 5000, new AbstractListener() {
|
||||
@Override
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
System.err.println(configInfo);
|
||||
System.out.println("receiveConfigInfo:" + configInfo);
|
||||
changedTmpContent[0] = configInfo;
|
||||
hasChangedCallback.set(true);
|
||||
}
|
||||
});
|
||||
hasListener.set(true);
|
||||
Assert.assertEquals(content, response);
|
||||
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.println("input content");
|
||||
while (scanner.hasNextLine()) {
|
||||
String s = scanner.next();
|
||||
if ("exit".equals(s)) {
|
||||
scanner.close();
|
||||
return;
|
||||
// new thread to publish config
|
||||
final String newRawContent = "nacosnewconfig-" + System.currentTimeMillis();
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (hasListener.get()) {
|
||||
try {
|
||||
configService.publishConfig(dataId, group, newRawContent);
|
||||
hasListener.set(false);
|
||||
break;
|
||||
} catch (NacosException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
configService.publishConfig(dataId, group, s);
|
||||
}
|
||||
}).start();
|
||||
|
||||
// spin
|
||||
do {
|
||||
if (hasChangedCallback.get()) {
|
||||
System.out.println(newRawContent + "==> " + changedTmpContent[0]);
|
||||
Assert.assertEquals(newRawContent, changedTmpContent[0]);
|
||||
break;
|
||||
}
|
||||
} while (!hasChangedCallback.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.client.config.listener.impl;
|
||||
|
||||
import com.alibaba.nacos.api.config.listener.Listener;
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;
|
||||
import com.alibaba.nacos.client.config.http.MetricsHttpAgent;
|
||||
import com.alibaba.nacos.client.config.impl.ClientWorker;
|
||||
import com.alibaba.nacos.client.utils.ParamUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class ClientWorkerTest {
|
||||
|
||||
@Mock
|
||||
ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
private ClientWorker clientWorker;
|
||||
|
||||
private List<Listener> listeners;
|
||||
|
||||
private final String dataId = "data";
|
||||
|
||||
private final String group = "group";
|
||||
|
||||
private final String currentLongingTaskCount = "currentLongingTaskCount";
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
clientWorker = new ClientWorker(mock(MetricsHttpAgent.class), mock(ConfigFilterChainManager.class),
|
||||
mock(Properties.class));
|
||||
try {
|
||||
Field executorServiceField = clientWorker.getClass().getDeclaredField("executorService");
|
||||
executorServiceField.setAccessible(true);
|
||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||
modifiersField.setAccessible(true);
|
||||
modifiersField.setInt(executorServiceField, executorServiceField.getModifiers() & ~Modifier.FINAL);
|
||||
executorServiceField.set(clientWorker, scheduledExecutorService);
|
||||
Listener listener = new Listener() {
|
||||
@Override
|
||||
public Executor getExecutor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
|
||||
}
|
||||
};
|
||||
listeners = Arrays.asList(listener);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddLongPollNumberThreads() {
|
||||
try {
|
||||
for (int i = 0; i < ParamUtil.getPerTaskConfigSize(); i++) {
|
||||
clientWorker.addTenantListeners(dataId + i, group, listeners);
|
||||
}
|
||||
Field currentLongingTaskCountField = clientWorker.getClass().getDeclaredField(currentLongingTaskCount);
|
||||
currentLongingTaskCountField.setAccessible(true);
|
||||
Assert.assertEquals(currentLongingTaskCount, (int) currentLongingTaskCountField.getDouble(clientWorker), 1);
|
||||
for (int i = (int) ParamUtil.getPerTaskConfigSize(); i < ParamUtil.getPerTaskConfigSize() * 2; i++) {
|
||||
clientWorker.addTenantListeners(dataId + i, group, listeners);
|
||||
}
|
||||
Assert.assertEquals(currentLongingTaskCount, (int) currentLongingTaskCountField.getDouble(clientWorker), 2);
|
||||
} catch (NacosException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReduceLongPollNumberThreads() {
|
||||
try {
|
||||
for (int i = 0; i < ParamUtil.getPerTaskConfigSize() * 3; i++) {
|
||||
clientWorker.addTenantListeners(dataId + i, group, listeners);
|
||||
}
|
||||
Field currentLongingTaskCountField = clientWorker.getClass().getDeclaredField(currentLongingTaskCount);
|
||||
currentLongingTaskCountField.setAccessible(true);
|
||||
Assert.assertEquals(currentLongingTaskCount, (int) currentLongingTaskCountField.getDouble(clientWorker), 3);
|
||||
|
||||
for (int i = (int) ParamUtil.getPerTaskConfigSize(); i < ParamUtil.getPerTaskConfigSize() * 2; i++) {
|
||||
clientWorker.removeTenantListener(dataId + i, group, listeners.get(0));
|
||||
}
|
||||
Assert.assertEquals(currentLongingTaskCount, (int) currentLongingTaskCountField.getDouble(clientWorker), 2);
|
||||
} catch (NacosException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.common.http;
|
||||
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.http.handler.ResponseHandler;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
@ -38,7 +39,9 @@ import java.net.URI;
|
||||
* Base http client.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.HttpClientRequest}
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class BaseHttpClient {
|
||||
|
||||
protected <T> RestResult<T> execute(CloseableHttpClient httpClient, final Type type, HttpUriRequest request)
|
||||
@ -79,7 +82,7 @@ public abstract class BaseHttpClient {
|
||||
|
||||
@Override
|
||||
public void cancelled() {
|
||||
|
||||
callback.onCancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -97,19 +100,11 @@ public abstract class BaseHttpClient {
|
||||
|
||||
protected HttpRequestBase build(String url, Header header, Object body, String method) throws Exception {
|
||||
|
||||
BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
|
||||
httpMethod.init(url);
|
||||
httpMethod.initHeader(header);
|
||||
httpMethod.initEntity(body, header.getValue("Content-Type"));
|
||||
return httpMethod.getRequestBase();
|
||||
}
|
||||
|
||||
private Header convertHeader(org.apache.http.Header[] headers) {
|
||||
final Header nHeader = Header.newInstance();
|
||||
for (org.apache.http.Header header : headers) {
|
||||
nHeader.addParam(header.getName(), header.getValue());
|
||||
}
|
||||
return nHeader;
|
||||
final BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
|
||||
final HttpRequestBase httpRequestBase = httpMethod.init(url);
|
||||
HttpUtils.initRequestHeader(httpRequestBase, header);
|
||||
HttpUtils.initRequestEntity(httpRequestBase, body, header.getValue(HttpHeaderConsts.CONTENT_TYPE));
|
||||
return httpRequestBase;
|
||||
}
|
||||
|
||||
public static class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
|
||||
|
@ -16,21 +16,9 @@
|
||||
|
||||
package com.alibaba.nacos.common.http;
|
||||
|
||||
import com.alibaba.nacos.common.http.handler.RequestHandler;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.utils.HttpMethod;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpHead;
|
||||
@ -39,9 +27,6 @@ import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.methods.HttpTrace;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
/**
|
||||
* Base http method.
|
||||
@ -139,78 +124,18 @@ public enum BaseHttpMethod {
|
||||
|
||||
private String name;
|
||||
|
||||
private HttpRequest requestBase;
|
||||
|
||||
BaseHttpMethod(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void init(String url) {
|
||||
requestBase = createRequest(url);
|
||||
public HttpRequestBase init(String url) {
|
||||
return createRequest(url);
|
||||
}
|
||||
|
||||
protected HttpRequestBase createRequest(String url) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init http header.
|
||||
*
|
||||
* @param header header
|
||||
*/
|
||||
public void initHeader(Header header) {
|
||||
Iterator<Map.Entry<String, String>> iterator = header.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, String> entry = iterator.next();
|
||||
requestBase.setHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init http entity.
|
||||
*
|
||||
* @param body body
|
||||
* @param mediaType mediaType {@link ContentType}
|
||||
* @throws Exception exception
|
||||
*/
|
||||
public void initEntity(Object body, String mediaType) throws Exception {
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (requestBase instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
|
||||
ContentType contentType = ContentType.create(mediaType);
|
||||
StringEntity entity = new StringEntity(RequestHandler.parse(body), contentType);
|
||||
request.setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init request from entity map.
|
||||
*
|
||||
* @param body body map
|
||||
* @param charset charset of entity
|
||||
* @throws Exception exception
|
||||
*/
|
||||
public void initFromEntity(Map<String, String> body, String charset) throws Exception {
|
||||
if (body == null || body.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<NameValuePair> params = new ArrayList<NameValuePair>(body.size());
|
||||
for (Map.Entry<String, String> entry : body.entrySet()) {
|
||||
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
if (requestBase instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
|
||||
HttpEntity entity = new UrlEncodedFormEntity(params, charset);
|
||||
request.setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public HttpRequestBase getRequestBase() {
|
||||
return (HttpRequestBase) requestBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value of {@link BaseHttpMethod}.
|
||||
*
|
||||
|
@ -39,4 +39,9 @@ public interface Callback<T> {
|
||||
*/
|
||||
void onError(Throwable throwable);
|
||||
|
||||
/**
|
||||
* Callback when the request is cancelled.
|
||||
*/
|
||||
void onCancel();
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
* Use the same HttpClient object in the same space.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @deprecated Refer to the new {@link HttpClientBeanHolder}
|
||||
*/
|
||||
@Deprecated
|
||||
public class HttpClientManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);
|
||||
|
@ -16,14 +16,25 @@
|
||||
|
||||
package com.alibaba.nacos.common.http;
|
||||
|
||||
import com.alibaba.nacos.common.http.handler.RequestHandler;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -40,6 +51,63 @@ public final class HttpUtils {
|
||||
|
||||
private static final Pattern CONTEXT_PATH_MATCH = Pattern.compile("(\\/)\\1+");
|
||||
|
||||
/**
|
||||
* Init http header.
|
||||
*
|
||||
* @param requestBase requestBase {@link HttpRequestBase}
|
||||
* @param header header
|
||||
*/
|
||||
public static void initRequestHeader(HttpRequestBase requestBase, Header header) {
|
||||
Iterator<Map.Entry<String, String>> iterator = header.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, String> entry = iterator.next();
|
||||
requestBase.setHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init http entity.
|
||||
*
|
||||
* @param requestBase requestBase {@link HttpRequestBase}
|
||||
* @param body body
|
||||
* @param mediaType mediaType {@link ContentType}
|
||||
* @throws Exception exception
|
||||
*/
|
||||
public static void initRequestEntity(HttpRequestBase requestBase, Object body, String mediaType) throws Exception {
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (requestBase instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
|
||||
ContentType contentType = ContentType.create(mediaType);
|
||||
StringEntity entity = new StringEntity(RequestHandler.parse(body), contentType);
|
||||
request.setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init request from entity map.
|
||||
*
|
||||
* @param requestBase requestBase {@link HttpRequestBase}
|
||||
* @param body body map
|
||||
* @param charset charset of entity
|
||||
* @throws Exception exception
|
||||
*/
|
||||
public static void initRequestFromEntity(HttpRequestBase requestBase, Map<String, String> body, String charset) throws Exception {
|
||||
if (body == null || body.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<NameValuePair> params = new ArrayList<NameValuePair>(body.size());
|
||||
for (Map.Entry<String, String> entry : body.entrySet()) {
|
||||
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
if (requestBase instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntityEnclosingRequest request = (HttpEntityEnclosingRequest) requestBase;
|
||||
HttpEntity entity = new UrlEncodedFormEntity(params, charset);
|
||||
request.setEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build URL.
|
||||
*
|
||||
|
@ -25,7 +25,9 @@ import java.lang.reflect.Type;
|
||||
* Nacos async http client interface.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate}
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("all")
|
||||
public interface NAsyncHttpClient extends NHttpClient {
|
||||
|
||||
|
@ -22,7 +22,9 @@ import java.io.Closeable;
|
||||
* Nacos http client interface.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.HttpClientRequest}
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
|
||||
public interface NHttpClient extends Closeable {
|
||||
|
||||
|
@ -26,7 +26,9 @@ import java.lang.reflect.Type;
|
||||
* Nacos sync http client.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.NacosRestTemplate}
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("all")
|
||||
public interface NSyncHttpClient extends NHttpClient {
|
||||
|
||||
|
@ -29,7 +29,9 @@ import java.lang.reflect.Type;
|
||||
* Nacos async http client.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.DefaultAsyncHttpClientRequest}
|
||||
*/
|
||||
@Deprecated
|
||||
class NacosAsyncHttpClient extends BaseHttpClient implements NAsyncHttpClient {
|
||||
|
||||
private CloseableHttpAsyncClient asyncClient;
|
||||
|
@ -30,7 +30,9 @@ import java.lang.reflect.Type;
|
||||
* Nacos sync http client.
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
* @deprecated Refer to the new {@link com.alibaba.nacos.common.http.client.request.JdkHttpClientRequest}
|
||||
*/
|
||||
@Deprecated
|
||||
class NacosSyncHttpClient extends BaseHttpClient implements NSyncHttpClient {
|
||||
|
||||
private CloseableHttpClient client;
|
||||
|
@ -61,10 +61,8 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param header http header param
|
||||
* @param query http query param
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void get(String url, Header header, Query query, Type responseType, Callback<T> callback)
|
||||
throws Exception {
|
||||
public <T> void get(String url, Header header, Query query, Type responseType, Callback<T> callback) {
|
||||
execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType, callback);
|
||||
}
|
||||
|
||||
@ -81,10 +79,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param paramValues paramValues
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void get(String url, Header header, Map<String, String> paramValues, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
Callback<T> callback) {
|
||||
execute(url, HttpMethod.GET, new RequestHttpEntity(header, Query.newInstance().initParams(paramValues)),
|
||||
responseType, callback);
|
||||
}
|
||||
@ -104,10 +101,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param body get with body
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void getLarge(String url, Header header, Query query, Object body, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
Callback<T> callback) {
|
||||
execute(url, HttpMethod.GET_LARGE, new RequestHttpEntity(header, query, body), responseType, callback);
|
||||
}
|
||||
|
||||
@ -124,10 +120,8 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param query http query param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void delete(String url, Header header, Query query, Type responseType, Callback<T> callback)
|
||||
throws Exception {
|
||||
public <T> void delete(String url, Header header, Query query, Type responseType, Callback<T> callback) {
|
||||
execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType, callback);
|
||||
}
|
||||
|
||||
@ -147,10 +141,8 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param body http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void put(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback)
|
||||
throws Exception {
|
||||
public <T> void put(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {
|
||||
execute(url, HttpMethod.PUT, new RequestHttpEntity(header, query, body), responseType, callback);
|
||||
}
|
||||
|
||||
@ -171,10 +163,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param body http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void putJson(String url, Header header, Map<String, String> paramValues, String body, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
Callback<T> callback) {
|
||||
execute(url, HttpMethod.PUT, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
|
||||
Query.newInstance().initParams(paramValues), body), responseType, callback);
|
||||
}
|
||||
@ -196,10 +187,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param bodyValues http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void putForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
Callback<T> callback) {
|
||||
execute(url, HttpMethod.PUT,
|
||||
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
|
||||
responseType, callback);
|
||||
@ -222,10 +212,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param bodyValues http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void putForm(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues,
|
||||
Type responseType, Callback<T> callback) throws Exception {
|
||||
Type responseType, Callback<T> callback) {
|
||||
execute(url, HttpMethod.PUT, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
|
||||
Query.newInstance().initParams(paramValues), bodyValues), responseType, callback);
|
||||
}
|
||||
@ -246,10 +235,8 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param body http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void post(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback)
|
||||
throws Exception {
|
||||
public <T> void post(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {
|
||||
execute(url, HttpMethod.POST, new RequestHttpEntity(header, query, body), responseType, callback);
|
||||
}
|
||||
|
||||
@ -270,10 +257,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param body http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void postJson(String url, Header header, Map<String, String> paramValues, String body, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
Callback<T> callback) {
|
||||
execute(url, HttpMethod.POST, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
|
||||
Query.newInstance().initParams(paramValues), body), responseType, callback);
|
||||
}
|
||||
@ -295,10 +281,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param bodyValues http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void postForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
|
||||
Callback<T> callback) throws Exception {
|
||||
Callback<T> callback) {
|
||||
execute(url, HttpMethod.POST,
|
||||
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
|
||||
responseType, callback);
|
||||
@ -321,10 +306,9 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
* @param bodyValues http body param
|
||||
* @param responseType return type
|
||||
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
|
||||
* @throws Exception ex
|
||||
*/
|
||||
public <T> void postForm(String url, Header header, Map<String, String> paramValues, Map<String, String> bodyValues,
|
||||
Type responseType, Callback<T> callback) throws Exception {
|
||||
Type responseType, Callback<T> callback) {
|
||||
execute(url, HttpMethod.POST,
|
||||
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED),
|
||||
Query.newInstance().initParams(paramValues), bodyValues), responseType, callback);
|
||||
@ -333,13 +317,18 @@ public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type type,
|
||||
Callback<T> callback) throws Exception {
|
||||
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
|
||||
Callback<T> callback) {
|
||||
try {
|
||||
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
|
||||
}
|
||||
ResponseHandler<T> responseHandler = super.selectResponseHandler(type);
|
||||
clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);
|
||||
} catch (Exception e) {
|
||||
// When an exception occurs, use Callback to pass it instead of throw it directly.
|
||||
callback.onError(e);
|
||||
}
|
||||
ResponseHandler<T> responseHandler = super.selectResponseHandler(type);
|
||||
clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,7 @@ public class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {
|
||||
|
||||
@Override
|
||||
public void cancelled() {
|
||||
|
||||
callback.onCancel();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.common.http.client.request;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.http.BaseHttpMethod;
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
import com.alibaba.nacos.common.http.HttpUtils;
|
||||
import com.alibaba.nacos.common.http.client.response.DefaultClientHttpResponse;
|
||||
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
@ -56,19 +57,18 @@ public class DefaultHttpClientRequest implements HttpClientRequest {
|
||||
}
|
||||
|
||||
static HttpRequestBase build(URI uri, String method, RequestHttpEntity requestHttpEntity) throws Exception {
|
||||
Header headers = requestHttpEntity.getHeaders();
|
||||
BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
|
||||
httpMethod.init(uri.toString());
|
||||
httpMethod.initHeader(headers);
|
||||
final Header headers = requestHttpEntity.getHeaders();
|
||||
final BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);
|
||||
final HttpRequestBase httpRequestBase = httpMethod.init(uri.toString());
|
||||
HttpUtils.initRequestHeader(httpRequestBase, headers);
|
||||
if (MediaType.APPLICATION_FORM_URLENCODED.equals(headers.getValue(HttpHeaderConsts.CONTENT_TYPE))
|
||||
&& requestHttpEntity.getBody() instanceof Map) {
|
||||
httpMethod.initFromEntity((Map<String, String>) requestHttpEntity.getBody(), headers.getCharset());
|
||||
HttpUtils.initRequestFromEntity(httpRequestBase, (Map<String, String>) requestHttpEntity.getBody(), headers.getCharset());
|
||||
} else {
|
||||
httpMethod.initEntity(requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE));
|
||||
HttpUtils.initRequestEntity(httpRequestBase, requestHttpEntity.getBody(), headers.getValue(HttpHeaderConsts.CONTENT_TYPE));
|
||||
}
|
||||
HttpRequestBase requestBase = httpMethod.getRequestBase();
|
||||
replaceDefaultConfig(requestBase, requestHttpEntity.getHttpClientConfig());
|
||||
return requestBase;
|
||||
replaceDefaultConfig(httpRequestBase, requestHttpEntity.getHttpClientConfig());
|
||||
return httpRequestBase;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,6 +44,6 @@ public final class MediaType {
|
||||
|
||||
public static final String TEXT_HTML = "text/html";
|
||||
|
||||
public static final String TEXT_PLAIN = "text/xml";
|
||||
public static final String TEXT_PLAIN = "text/plain";
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -16,11 +16,10 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.auth;
|
||||
|
||||
import com.alibaba.nacos.core.auth.Resource;
|
||||
import com.alibaba.nacos.core.auth.ResourceParser;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.alibaba.nacos.auth.model.Resource;
|
||||
import com.alibaba.nacos.auth.parser.ResourceParser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,7 @@ import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.ROLE_INFO_ROW_MAPPER;
|
||||
|
||||
@ -134,4 +135,11 @@ public class EmbeddedRolePersistServiceImpl implements RolePersistService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findRolesLikeRoleName(String role) {
|
||||
String sql = "SELECT role FROM roles WHERE role like ? ";
|
||||
List<String> users = databaseOperate.queryMany(sql, new String[] {"%" + role + "%"}, String.class);
|
||||
return users;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.USER_ROW_MAPPER;
|
||||
|
||||
@ -117,4 +118,11 @@ public class EmbeddedUserPersistServiceImpl implements UserPersistService {
|
||||
}
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findUserLikeUsername(String username) {
|
||||
String sql = "SELECT username FROM users WHERE username like ? ";
|
||||
List<String> users = databaseOperate.queryMany(sql, new String[] {"%" + username + "%"}, String.class);
|
||||
return users;
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import javax.annotation.PostConstruct;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.ROLE_INFO_ROW_MAPPER;
|
||||
|
||||
@ -152,6 +153,13 @@ public class ExternalRolePersistServiceImpl implements RolePersistService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findRolesLikeRoleName(String role) {
|
||||
String sql = "SELECT role FROM roles WHERE role like '%' ? '%'";
|
||||
List<String> users = this.jt.queryForList(sql, new String[]{role}, String.class);
|
||||
return users;
|
||||
}
|
||||
|
||||
private static final class RoleInfoRowMapper implements RowMapper<RoleInfo> {
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +31,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.USER_ROW_MAPPER;
|
||||
|
||||
@ -145,4 +146,11 @@ public class ExternalUserPersistServiceImpl implements UserPersistService {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findUserLikeUsername(String username) {
|
||||
String sql = "SELECT username FROM users WHERE username like '%' ? '%'";
|
||||
List<String> users = this.jt.queryForList(sql, new String[]{username}, String.class);
|
||||
return users;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package com.alibaba.nacos.config.server.auth;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Role CRUD service.
|
||||
*
|
||||
@ -37,4 +39,5 @@ public interface RolePersistService {
|
||||
|
||||
void deleteRole(String role, String username);
|
||||
|
||||
List<String> findRolesLikeRoleName(String role);
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ package com.alibaba.nacos.config.server.auth;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.model.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User CRUD service.
|
||||
*
|
||||
@ -37,5 +39,7 @@ public interface UserPersistService {
|
||||
User findUserByUsername(String username);
|
||||
|
||||
Page<User> getUsers(int pageNo, int pageSize);
|
||||
|
||||
|
||||
List<String> findUserLikeUsername(String username);
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
package com.alibaba.nacos.config.server.controller;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.MapUtils;
|
||||
import com.alibaba.nacos.config.server.auth.ConfigResourceParser;
|
||||
@ -43,8 +45,6 @@ import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.alibaba.nacos.config.server.utils.ZipUtils;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
@ -134,6 +134,7 @@ public class ConfigController {
|
||||
|
||||
final String srcIp = RequestUtil.getRemoteIp(request);
|
||||
final String requestIpApp = RequestUtil.getAppName(request);
|
||||
srcUser = RequestUtil.getSrcUserName(request);
|
||||
// check tenant
|
||||
ParamUtils.checkTenant(tenant);
|
||||
ParamUtils.checkParam(dataId, group, "datumId", content);
|
||||
@ -183,8 +184,8 @@ public class ConfigController {
|
||||
* Get configure board infomation fail.
|
||||
*
|
||||
* @throws ServletException ServletException.
|
||||
* @throws IOException IOException.
|
||||
* @throws NacosException NacosException.
|
||||
* @throws IOException IOException.
|
||||
* @throws NacosException NacosException.
|
||||
*/
|
||||
@GetMapping
|
||||
@Secured(action = ActionTypes.READ, parser = ConfigResourceParser.class)
|
||||
@ -239,10 +240,11 @@ public class ConfigController {
|
||||
ParamUtils.checkParam(dataId, group, "datumId", "rm");
|
||||
ParamUtils.checkParam(tag);
|
||||
String clientIp = RequestUtil.getRemoteIp(request);
|
||||
String srcUser = RequestUtil.getSrcUserName(request);
|
||||
if (StringUtils.isBlank(tag)) {
|
||||
persistService.removeConfigInfo(dataId, group, tenant, clientIp, null);
|
||||
persistService.removeConfigInfo(dataId, group, tenant, clientIp, srcUser);
|
||||
} else {
|
||||
persistService.removeConfigInfoTag(dataId, group, tenant, tag, clientIp, null);
|
||||
persistService.removeConfigInfoTag(dataId, group, tenant, tag, clientIp, srcUser);
|
||||
}
|
||||
final Timestamp time = TimeUtils.getCurrentTime();
|
||||
ConfigTraceService.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), clientIp,
|
||||
@ -394,7 +396,7 @@ public class ConfigController {
|
||||
* Execute to remove beta operation.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @return Execute to operate result.
|
||||
*/
|
||||
@ -425,7 +427,7 @@ public class ConfigController {
|
||||
* Execute to query beta operation.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param group group string value.
|
||||
* @param tenant tenant string value.
|
||||
* @return RestResult for ConfigInfo4Beta.
|
||||
*/
|
||||
@ -452,11 +454,11 @@ public class ConfigController {
|
||||
/**
|
||||
* Execute export config operation.
|
||||
*
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param dataId dataId string value.
|
||||
* @param group group string value.
|
||||
* @param appName appName string value.
|
||||
* @param tenant tenant string value.
|
||||
* @param ids id list value.
|
||||
* @param tenant tenant string value.
|
||||
* @param ids id list value.
|
||||
* @return ResponseEntity.
|
||||
*/
|
||||
@GetMapping(params = "export=true")
|
||||
@ -504,11 +506,11 @@ public class ConfigController {
|
||||
/**
|
||||
* Execute import and publish config operation.
|
||||
*
|
||||
* @param request http servlet request .
|
||||
* @param srcUser src user string value.
|
||||
* @param request http servlet request .
|
||||
* @param srcUser src user string value.
|
||||
* @param namespace namespace string value.
|
||||
* @param policy policy model.
|
||||
* @param file MultipartFile.
|
||||
* @param policy policy model.
|
||||
* @param file MultipartFile.
|
||||
* @return RestResult Map.
|
||||
* @throws NacosException NacosException.
|
||||
*/
|
||||
@ -605,11 +607,11 @@ public class ConfigController {
|
||||
/**
|
||||
* Execute clone config operation.
|
||||
*
|
||||
* @param request http servlet request .
|
||||
* @param srcUser src user string value.
|
||||
* @param namespace namespace string value.
|
||||
* @param request http servlet request .
|
||||
* @param srcUser src user string value.
|
||||
* @param namespace namespace string value.
|
||||
* @param configBeansList config beans list.
|
||||
* @param policy config policy model.
|
||||
* @param policy config policy model.
|
||||
* @return RestResult for map.
|
||||
* @throws NacosException NacosException.
|
||||
*/
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.common.utils.Objects;
|
||||
@ -29,8 +31,6 @@ import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.repository.embedded.DatabaseOperate;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.controller;
|
||||
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.enums.FileTypeEnum;
|
||||
import com.alibaba.nacos.config.server.model.CacheItem;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoBase;
|
||||
import com.alibaba.nacos.config.server.service.ConfigCacheService;
|
||||
@ -136,8 +138,18 @@ public class ConfigServletInner {
|
||||
isBeta = true;
|
||||
}
|
||||
}
|
||||
String configType = cacheItem.getType();
|
||||
response.setHeader("Config-Type", (null != configType) ? configType : "text");
|
||||
|
||||
final String configType =
|
||||
(null != cacheItem.getType()) ? cacheItem.getType() : FileTypeEnum.TEXT.getFileType();
|
||||
response.setHeader("Config-Type", configType);
|
||||
|
||||
String contentTypeHeader;
|
||||
try {
|
||||
contentTypeHeader = FileTypeEnum.valueOf(configType.toUpperCase()).getContentType();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
contentTypeHeader = FileTypeEnum.TEXT.getContentType();
|
||||
}
|
||||
response.setHeader(HttpHeaderConsts.CONTENT_TYPE, contentTypeHeader);
|
||||
}
|
||||
File file = null;
|
||||
ConfigInfoBase configInfoBase = null;
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.enums;
|
||||
|
||||
import com.alibaba.nacos.common.http.param.MediaType;
|
||||
|
||||
/**
|
||||
* Config file type enum.
|
||||
*
|
||||
@ -27,58 +29,73 @@ public enum FileTypeEnum {
|
||||
/**
|
||||
* Yaml file.
|
||||
*/
|
||||
YML("yaml"),
|
||||
YML("yaml", MediaType.TEXT_PLAIN),
|
||||
|
||||
/**
|
||||
* Yaml file.
|
||||
*/
|
||||
YAML("yaml"),
|
||||
YAML("yaml", MediaType.TEXT_PLAIN),
|
||||
|
||||
/**
|
||||
* Text file.
|
||||
*/
|
||||
TXT("text"),
|
||||
TXT("text", MediaType.TEXT_PLAIN),
|
||||
|
||||
/**
|
||||
* Text file.
|
||||
*/
|
||||
TEXT("text"),
|
||||
TEXT("text", MediaType.TEXT_PLAIN),
|
||||
|
||||
/**
|
||||
* Json file.
|
||||
*/
|
||||
JSON("json"),
|
||||
JSON("json", MediaType.APPLICATION_JSON),
|
||||
|
||||
/**
|
||||
* Xml file.
|
||||
*/
|
||||
XML("xml"),
|
||||
XML("xml", MediaType.APPLICATION_XML),
|
||||
|
||||
/**
|
||||
* Html file.
|
||||
*/
|
||||
HTM("html"),
|
||||
HTM("html", MediaType.TEXT_HTML),
|
||||
|
||||
/**
|
||||
* Html file.
|
||||
*/
|
||||
HTML("html"),
|
||||
HTML("html", MediaType.TEXT_HTML),
|
||||
|
||||
/**
|
||||
* Properties file.
|
||||
*/
|
||||
PROPERTIES("properties");
|
||||
PROPERTIES("properties", MediaType.TEXT_PLAIN);
|
||||
|
||||
/**
|
||||
* File type corresponding to file extension.
|
||||
*/
|
||||
private String fileType;
|
||||
|
||||
/**
|
||||
* Http Content type corresponding to file extension.
|
||||
*/
|
||||
private String contentType;
|
||||
|
||||
FileTypeEnum(String fileType) {
|
||||
this.fileType = fileType;
|
||||
this.contentType = MediaType.TEXT_PLAIN;
|
||||
}
|
||||
|
||||
FileTypeEnum(String fileType, String contentType) {
|
||||
this.fileType = fileType;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public String getFileType() {
|
||||
return this.fileType;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.config.server.model.AclInfo;
|
||||
import com.alibaba.nacos.config.server.utils.JSONUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -76,7 +76,7 @@ public class ClientIpWhiteList {
|
||||
}
|
||||
DEFAULT_LOG.warn("[clientIpWhiteList] {}", content);
|
||||
try {
|
||||
AclInfo acl = (AclInfo) JSONUtils.deserializeObject(content, AclInfo.class);
|
||||
AclInfo acl = JacksonUtils.toObj(content, AclInfo.class);
|
||||
isOpen = acl.getIsOpen();
|
||||
CLIENT_IP_WHITELIST.set(acl.getIps());
|
||||
} catch (Exception ioe) {
|
||||
|
@ -16,21 +16,20 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.SampleResult;
|
||||
import com.alibaba.nacos.config.server.service.notify.NotifyService;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.JSONUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -178,19 +177,15 @@ public class ConfigSubService {
|
||||
}
|
||||
|
||||
String urlAll = getUrl(ip, url) + "?" + paramUrl;
|
||||
com.alibaba.nacos.config.server.service.notify.NotifyService.HttpResult result = NotifyService
|
||||
RestResult<String> result = NotifyService
|
||||
.invokeURL(urlAll, null, Constants.ENCODE);
|
||||
|
||||
// Http code 200
|
||||
if (result.code == HttpURLConnection.HTTP_OK) {
|
||||
String json = result.content;
|
||||
SampleResult resultObj = JSONUtils.deserializeObject(json, new TypeReference<SampleResult>() {
|
||||
});
|
||||
return resultObj;
|
||||
|
||||
if (result.ok()) {
|
||||
return JacksonUtils.toObj(result.getData(), SampleResult.class);
|
||||
} else {
|
||||
|
||||
LogUtil.DEFAULT_LOG.info("Can not get clientInfo from {} with {}", ip, result.code);
|
||||
LogUtil.DEFAULT_LOG.info("Can not get clientInfo from {} with {}", ip, result.getData());
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -16,6 +16,11 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.common.http.Callback;
|
||||
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
@ -25,20 +30,11 @@ import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.utils.HttpClientUtils;
|
||||
import org.apache.http.concurrent.FutureCallback;
|
||||
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
|
||||
import org.apache.http.impl.nio.client.HttpAsyncClients;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -63,7 +59,6 @@ public class AsyncNotifyService {
|
||||
@Autowired
|
||||
public AsyncNotifyService(ServerMemberManager memberManager) {
|
||||
this.memberManager = memberManager;
|
||||
httpclient.start();
|
||||
|
||||
// Register ConfigDataChangeEvent to NotifyCenter.
|
||||
NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);
|
||||
@ -89,7 +84,7 @@ public class AsyncNotifyService {
|
||||
queue.add(new NotifySingleTask(dataId, group, tenant, tag, dumpTs, member.getAddress(),
|
||||
evt.isBeta));
|
||||
}
|
||||
ConfigExecutor.executeAsyncNotify(new AsyncTask(httpclient, queue));
|
||||
ConfigExecutor.executeAsyncNotify(new AsyncTask(nacosAsyncRestTemplate, queue));
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,12 +95,7 @@ public class AsyncNotifyService {
|
||||
});
|
||||
}
|
||||
|
||||
private RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setConnectTimeout(PropertyUtil.getNotifyConnectTimeout())
|
||||
.setSocketTimeout(PropertyUtil.getNotifySocketTimeout()).build();
|
||||
|
||||
private CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig)
|
||||
.build();
|
||||
private final NacosAsyncRestTemplate nacosAsyncRestTemplate = HttpClientManager.getNacosAsyncRestTemplate();
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncNotifyService.class);
|
||||
|
||||
@ -113,8 +103,12 @@ public class AsyncNotifyService {
|
||||
|
||||
class AsyncTask implements Runnable {
|
||||
|
||||
public AsyncTask(CloseableHttpAsyncClient httpclient, Queue<NotifySingleTask> queue) {
|
||||
this.httpclient = httpclient;
|
||||
private Queue<NotifySingleTask> queue;
|
||||
|
||||
private NacosAsyncRestTemplate restTemplate;
|
||||
|
||||
public AsyncTask(NacosAsyncRestTemplate restTemplate, Queue<NotifySingleTask> queue) {
|
||||
this.restTemplate = restTemplate;
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
@ -138,52 +132,47 @@ public class AsyncNotifyService {
|
||||
// get delay time and set fail count to the task
|
||||
asyncTaskExecute(task);
|
||||
} else {
|
||||
HttpGet request = new HttpGet(task.url);
|
||||
request.setHeader(NotifyService.NOTIFY_HEADER_LAST_MODIFIED,
|
||||
String.valueOf(task.getLastModified()));
|
||||
request.setHeader(NotifyService.NOTIFY_HEADER_OP_HANDLE_IP, InetUtils.getSelfIp());
|
||||
Header header = Header.newInstance();
|
||||
header.addParam(NotifyService.NOTIFY_HEADER_LAST_MODIFIED, String.valueOf(task.getLastModified()));
|
||||
header.addParam(NotifyService.NOTIFY_HEADER_OP_HANDLE_IP, InetUtils.getSelfIp());
|
||||
if (task.isBeta) {
|
||||
request.setHeader("isBeta", "true");
|
||||
header.addParam("isBeta", "true");
|
||||
}
|
||||
httpclient.execute(request, new AsyncNotifyCallBack(httpclient, task));
|
||||
restTemplate.get(task.url, header, Query.EMPTY, String.class, new AsyncNotifyCallBack(task));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Queue<NotifySingleTask> queue;
|
||||
|
||||
private CloseableHttpAsyncClient httpclient;
|
||||
|
||||
}
|
||||
|
||||
private void asyncTaskExecute(NotifySingleTask task) {
|
||||
int delay = getDelayTime(task);
|
||||
Queue<NotifySingleTask> queue = new LinkedList<NotifySingleTask>();
|
||||
queue.add(task);
|
||||
AsyncTask asyncTask = new AsyncTask(httpclient, queue);
|
||||
AsyncTask asyncTask = new AsyncTask(nacosAsyncRestTemplate, queue);
|
||||
ConfigExecutor.scheduleAsyncNotify(asyncTask, delay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
class AsyncNotifyCallBack implements FutureCallback<HttpResponse> {
|
||||
class AsyncNotifyCallBack implements Callback<String> {
|
||||
|
||||
private NotifySingleTask task;
|
||||
|
||||
public AsyncNotifyCallBack(CloseableHttpAsyncClient httpClient, NotifySingleTask task) {
|
||||
public AsyncNotifyCallBack(NotifySingleTask task) {
|
||||
this.task = task;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completed(HttpResponse response) {
|
||||
public void onReceive(RestResult<String> result) {
|
||||
|
||||
long delayed = System.currentTimeMillis() - task.getLastModified();
|
||||
|
||||
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
||||
if (result.ok()) {
|
||||
ConfigTraceService.logNotifyEvent(task.getDataId(), task.getGroup(), task.getTenant(), null,
|
||||
task.getLastModified(), InetUtils.getSelfIp(), ConfigTraceService.NOTIFY_EVENT_OK, delayed,
|
||||
task.target);
|
||||
} else {
|
||||
LOGGER.error("[notify-error] target:{} dataId:{} group:{} ts:{} code:{}", task.target, task.getDataId(),
|
||||
task.getGroup(), task.getLastModified(), response.getStatusLine().getStatusCode());
|
||||
task.getGroup(), task.getLastModified(), result.getCode());
|
||||
ConfigTraceService.logNotifyEvent(task.getDataId(), task.getGroup(), task.getTenant(), null,
|
||||
task.getLastModified(), InetUtils.getSelfIp(), ConfigTraceService.NOTIFY_EVENT_ERROR, delayed,
|
||||
task.target);
|
||||
@ -197,11 +186,10 @@ public class AsyncNotifyService {
|
||||
|
||||
MetricsMonitor.getConfigNotifyException().increment();
|
||||
}
|
||||
HttpClientUtils.closeQuietly(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Exception ex) {
|
||||
public void onError(Throwable ex) {
|
||||
|
||||
long delayed = System.currentTimeMillis() - task.getLastModified();
|
||||
LOGGER.error("[notify-exception] target:{} dataId:{} group:{} ts:{} ex:{}", task.target, task.getDataId(),
|
||||
@ -219,7 +207,7 @@ public class AsyncNotifyService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelled() {
|
||||
public void onCancel() {
|
||||
|
||||
LogUtil.NOTIFY_LOG.error("[notify-exception] target:{} dataId:{} group:{} ts:{} method:{}", task.target,
|
||||
task.getDataId(), task.getGroup(), task.getLastModified(), "CANCELED");
|
||||
@ -231,10 +219,6 @@ public class AsyncNotifyService {
|
||||
|
||||
MetricsMonitor.getConfigNotifyException().increment();
|
||||
}
|
||||
|
||||
private NotifySingleTask task;
|
||||
|
||||
private CloseableHttpAsyncClient httpClient;
|
||||
}
|
||||
|
||||
static class NotifySingleTask extends NotifyTask {
|
||||
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.common.http.AbstractHttpClientFactory;
|
||||
import com.alibaba.nacos.common.http.HttpClientBeanHolder;
|
||||
import com.alibaba.nacos.common.http.HttpClientConfig;
|
||||
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
|
||||
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* http client manager.
|
||||
*
|
||||
* @author mai.jh
|
||||
*/
|
||||
public final class HttpClientManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);
|
||||
|
||||
/**
|
||||
* Connection timeout and socket timeout with other servers.
|
||||
*/
|
||||
private static final int TIMEOUT = 500;
|
||||
|
||||
private static final NacosRestTemplate NACOS_REST_TEMPLATE;
|
||||
|
||||
private static final NacosAsyncRestTemplate NACOS_ASYNC_REST_TEMPLATE;
|
||||
|
||||
static {
|
||||
// build nacos rest template
|
||||
NACOS_REST_TEMPLATE = HttpClientBeanHolder.getNacosRestTemplate(new ConfigHttpClientFactory(TIMEOUT, TIMEOUT));
|
||||
NACOS_ASYNC_REST_TEMPLATE = HttpClientBeanHolder.getNacosAsyncRestTemplate(
|
||||
new ConfigHttpClientFactory(PropertyUtil.getNotifyConnectTimeout(),
|
||||
PropertyUtil.getNotifySocketTimeout()));
|
||||
|
||||
ThreadUtils.addShutdownHook(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static NacosRestTemplate getNacosRestTemplate() {
|
||||
return NACOS_REST_TEMPLATE;
|
||||
}
|
||||
|
||||
public static NacosAsyncRestTemplate getNacosAsyncRestTemplate() {
|
||||
return NACOS_ASYNC_REST_TEMPLATE;
|
||||
}
|
||||
|
||||
private static void shutdown() {
|
||||
LOGGER.warn("[ConfigServer-HttpClientManager] Start destroying NacosRestTemplate");
|
||||
try {
|
||||
final String httpClientFactoryBeanName = ConfigHttpClientFactory.class.getName();
|
||||
HttpClientBeanHolder.shutdownNacostSyncRest(httpClientFactoryBeanName);
|
||||
HttpClientBeanHolder.shutdownNacosAsyncRest(httpClientFactoryBeanName);
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("[ConfigServer-HttpClientManager] An exception occurred when the HTTP client was closed : {}",
|
||||
ExceptionUtil.getStackTrace(ex));
|
||||
}
|
||||
LOGGER.warn("[ConfigServer-HttpClientManager] Destruction of the end");
|
||||
}
|
||||
|
||||
/**
|
||||
* http client factory.
|
||||
*/
|
||||
private static class ConfigHttpClientFactory extends AbstractHttpClientFactory {
|
||||
|
||||
private final int conTimeOutMillis;
|
||||
|
||||
private final int readTimeOutMillis;
|
||||
|
||||
public ConfigHttpClientFactory(int conTimeOutMillis, int readTimeOutMillis) {
|
||||
this.conTimeOutMillis = conTimeOutMillis;
|
||||
this.readTimeOutMillis = readTimeOutMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpClientConfig buildHttpClientConfig() {
|
||||
return HttpClientConfig.builder().setConTimeOutMillis(conTimeOutMillis)
|
||||
.setReadTimeOutMillis(readTimeOutMillis).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Logger assignLogger() {
|
||||
return LOGGER;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,17 +16,15 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
|
||||
import com.alibaba.nacos.common.http.param.Header;
|
||||
import com.alibaba.nacos.common.http.param.Query;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.config.server.manager.TaskManager;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -53,65 +51,24 @@ public class NotifyService {
|
||||
|
||||
public static final String NOTIFY_HEADER_OP_HANDLE_IP = "opHandleIp";
|
||||
|
||||
private TaskManager notifyTaskManager;
|
||||
|
||||
/**
|
||||
* Invoke http get request.
|
||||
*
|
||||
* @param url url
|
||||
* @param headers headers
|
||||
* @param encoding encoding
|
||||
* @return {@link HttpResult}
|
||||
* @throws IOException throw IOException
|
||||
* @return {@link com.alibaba.nacos.common.model.RestResult}
|
||||
* @throws Exception throw Exception
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
|
||||
public static HttpResult invokeURL(String url, List<String> headers, String encoding) throws IOException {
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
conn = (HttpURLConnection) new URL(url).openConnection();
|
||||
|
||||
conn.setConnectTimeout(TIMEOUT);
|
||||
conn.setReadTimeout(TIMEOUT);
|
||||
conn.setRequestMethod("GET");
|
||||
|
||||
if (null != headers && !StringUtils.isEmpty(encoding)) {
|
||||
for (Iterator<String> iter = headers.iterator(); iter.hasNext(); ) {
|
||||
conn.addRequestProperty(iter.next(), iter.next());
|
||||
}
|
||||
}
|
||||
conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + encoding);
|
||||
// establish TCP connection
|
||||
conn.connect();
|
||||
// Send request internally
|
||||
int respCode = conn.getResponseCode();
|
||||
String resp = null;
|
||||
|
||||
if (HttpServletResponse.SC_OK == respCode) {
|
||||
resp = IoUtils.toString(conn.getInputStream(), encoding);
|
||||
} else {
|
||||
resp = IoUtils.toString(conn.getErrorStream(), encoding);
|
||||
}
|
||||
return new HttpResult(respCode, resp);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(conn);
|
||||
public static RestResult<String> invokeURL(String url, List<String> headers, String encoding) throws Exception {
|
||||
Header header = Header.newInstance();
|
||||
header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, encoding);
|
||||
if (CollectionUtils.isNotEmpty(headers)) {
|
||||
header.addAll(headers);
|
||||
}
|
||||
return HttpClientManager.getNacosRestTemplate().get(url, header, Query.EMPTY, String.class);
|
||||
}
|
||||
|
||||
public static class HttpResult {
|
||||
|
||||
public final int code;
|
||||
|
||||
public String content;
|
||||
|
||||
public HttpResult(int code, String content) {
|
||||
this.code = code;
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection timeout and socket timeout with other servers.
|
||||
*/
|
||||
static final int TIMEOUT = 500;
|
||||
|
||||
private TaskManager notifyTaskManager;
|
||||
|
||||
}
|
||||
|
@ -16,17 +16,16 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.manager.AbstractTask;
|
||||
import com.alibaba.nacos.config.server.manager.TaskProcessor;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.service.notify.NotifyService.HttpResult;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -78,8 +77,8 @@ public class NotifyTaskProcessor implements TaskProcessor {
|
||||
String urlString = MessageFormat
|
||||
.format(URL_PATTERN, serverIp, ApplicationUtils.getContextPath(), dataId, group);
|
||||
|
||||
HttpResult result = NotifyService.invokeURL(urlString, headers, Constants.ENCODE);
|
||||
if (result.code == HttpStatus.SC_OK) {
|
||||
RestResult<String> result = NotifyService.invokeURL(urlString, headers, Constants.ENCODE);
|
||||
if (result.ok()) {
|
||||
ConfigTraceService.logNotifyEvent(dataId, group, tenant, null, lastModified, InetUtils.getSelfIp(),
|
||||
ConfigTraceService.NOTIFY_EVENT_OK, delayed, serverIp);
|
||||
|
||||
@ -89,7 +88,7 @@ public class NotifyTaskProcessor implements TaskProcessor {
|
||||
} else {
|
||||
MetricsMonitor.getConfigNotifyException().increment();
|
||||
LOGGER.error("[notify-error] {}, {}, to {}, result {}",
|
||||
new Object[] {dataId, group, serverIp, result.code});
|
||||
new Object[] {dataId, group, serverIp, result.getCode()});
|
||||
ConfigTraceService.logNotifyEvent(dataId, group, tenant, null, lastModified, InetUtils.getSelfIp(),
|
||||
ConfigTraceService.NOTIFY_EVENT_ERROR, delayed, serverIp);
|
||||
return false;
|
||||
|
@ -475,6 +475,7 @@ public final class RowMapperManager {
|
||||
configHistoryInfo.setTenant(rs.getString("tenant_id"));
|
||||
configHistoryInfo.setAppName(rs.getString("app_name"));
|
||||
configHistoryInfo.setSrcIp(rs.getString("src_ip"));
|
||||
configHistoryInfo.setSrcUser(rs.getString("src_user"));
|
||||
configHistoryInfo.setOpType(rs.getString("op_type"));
|
||||
configHistoryInfo.setCreatedTime(rs.getTimestamp("gmt_create"));
|
||||
configHistoryInfo.setLastModifiedTime(rs.getTimestamp("gmt_modified"));
|
||||
|
@ -2005,7 +2005,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
int pageSize) {
|
||||
String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;
|
||||
String sqlCountRows = "select count(*) from his_config_info where data_id = ? and group_id = ? and tenant_id = ?";
|
||||
String sqlFetchRows = "select nid,data_id,group_id,tenant_id,app_name,src_ip,op_type,gmt_create,gmt_modified from his_config_info where data_id = ? and group_id = ? and tenant_id = ? order by nid desc";
|
||||
String sqlFetchRows = "select nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,gmt_create,gmt_modified from his_config_info where data_id = ? and group_id = ? and tenant_id = ? order by nid desc";
|
||||
|
||||
PaginationHelper<ConfigHistoryInfo> helper = createPaginationHelper();
|
||||
return helper.fetchPage(sqlCountRows, sqlFetchRows, new Object[] {dataId, group, tenantTmp}, pageNo, pageSize,
|
||||
|
@ -2240,7 +2240,7 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
|
||||
String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;
|
||||
String sqlCountRows = "select count(*) from his_config_info where data_id = ? and group_id = ? and tenant_id = ?";
|
||||
String sqlFetchRows =
|
||||
"select nid,data_id,group_id,tenant_id,app_name,src_ip,op_type,gmt_create,gmt_modified from his_config_info "
|
||||
"select nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,gmt_create,gmt_modified from his_config_info "
|
||||
+ "where data_id = ? and group_id = ? and tenant_id = ? order by nid desc";
|
||||
|
||||
Page<ConfigHistoryInfo> page = null;
|
||||
@ -2249,7 +2249,8 @@ public class ExternalStoragePersistServiceImpl implements PersistService {
|
||||
.fetchPage(sqlCountRows, sqlFetchRows, new Object[] {dataId, group, tenantTmp}, pageNo, pageSize,
|
||||
HISTORY_LIST_ROW_MAPPER);
|
||||
} catch (DataAccessException e) {
|
||||
LogUtil.FATAL_LOG.error("[list-config-history] error, dataId:{}, group:{}", new Object[] {dataId, group}, e);
|
||||
LogUtil.FATAL_LOG
|
||||
.error("[list-config-history] error, dataId:{}, group:{}", new Object[] {dataId, group}, e);
|
||||
throw e;
|
||||
}
|
||||
return page;
|
||||
|
@ -1,57 +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.config.server.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
||||
/**
|
||||
* Json util.
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@SuppressWarnings({"PMD.ClassNamingShouldBeCamelRule", "checkstyle:AbbreviationAsWordInName"})
|
||||
public class JSONUtils {
|
||||
|
||||
static ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
static {
|
||||
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
}
|
||||
|
||||
public static String serializeObject(Object o) throws IOException {
|
||||
return mapper.writeValueAsString(o);
|
||||
}
|
||||
|
||||
public static Object deserializeObject(String s, Class<?> clazz) throws IOException {
|
||||
return mapper.readValue(s, clazz);
|
||||
}
|
||||
|
||||
public static <T> T deserializeObject(String s, TypeReference<T> typeReference) throws IOException {
|
||||
return mapper.readValue(s, typeReference);
|
||||
}
|
||||
|
||||
public static <T> T deserializeObject(InputStream src, TypeReference<T> typeReference) throws IOException {
|
||||
return mapper.readValue(src, typeReference);
|
||||
}
|
||||
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import com.alibaba.nacos.auth.model.User;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -35,6 +36,8 @@ public class RequestUtil {
|
||||
|
||||
public static final String CLIENT_APPNAME_HEADER = "Client-AppName";
|
||||
|
||||
public static final String NACOS_USER_KEY = "nacosuser";
|
||||
|
||||
/**
|
||||
* get real client ip
|
||||
*
|
||||
@ -63,4 +66,31 @@ public class RequestUtil {
|
||||
return request.getHeader(CLIENT_APPNAME_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user of the client application in the Attribute.
|
||||
*
|
||||
* @param request {@link HttpServletRequest}
|
||||
* @return may be return null
|
||||
*/
|
||||
public static User getUser(HttpServletRequest request) {
|
||||
Object userObj = request.getAttribute(NACOS_USER_KEY);
|
||||
if (userObj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
User user = (User) userObj;
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username of the client application in the Attribute.
|
||||
*
|
||||
* @param request {@link HttpServletRequest}
|
||||
* @return may be return null
|
||||
*/
|
||||
public static String getSrcUserName(HttpServletRequest request) {
|
||||
User user = getUser(request);
|
||||
return user == null ? null : user.getUserName();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -85,7 +85,7 @@
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-all</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>nacos-console</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@ -76,20 +76,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -16,14 +16,14 @@
|
||||
|
||||
package com.alibaba.nacos.console.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.config.server.model.TenantInfo;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.console.model.Namespace;
|
||||
import com.alibaba.nacos.console.model.NamespaceAllInfo;
|
||||
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
package com.alibaba.nacos.console.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
|
||||
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
package com.alibaba.nacos.console.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
|
||||
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@ -30,6 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Role operation controller.
|
||||
*
|
||||
@ -58,6 +60,18 @@ public class RoleController {
|
||||
return roleService.getRolesFromDatabase(username, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fuzzy matching role name .
|
||||
*
|
||||
* @param role role id
|
||||
* @return role list
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
|
||||
public List<String> searchRoles(@RequestParam String role) {
|
||||
return roleService.findRolesLikeRoleName(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a role to a user
|
||||
*
|
||||
|
@ -17,6 +17,11 @@
|
||||
package com.alibaba.nacos.console.controller;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.auth.common.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.common.AuthSystemTypes;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.config.server.auth.RoleInfo;
|
||||
@ -28,11 +33,6 @@ import com.alibaba.nacos.console.security.nacos.users.NacosUser;
|
||||
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.console.utils.JwtTokenUtils;
|
||||
import com.alibaba.nacos.console.utils.PasswordEncoderUtil;
|
||||
import com.alibaba.nacos.core.auth.AccessException;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.AuthConfigs;
|
||||
import com.alibaba.nacos.core.auth.AuthSystemTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@ -248,4 +248,17 @@ public class UserController {
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fuzzy matching username.
|
||||
*
|
||||
* @param username username
|
||||
* @return Matched username
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
|
||||
public List<String> searchUsersLikeUsername(@RequestParam String username) {
|
||||
return userDetailsService.findUserLikeUsername(username);
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.console.exception;
|
||||
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.core.auth.AccessException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
package com.alibaba.nacos.console.security.nacos;
|
||||
|
||||
import com.alibaba.nacos.core.auth.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.common.AuthConfigs;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -69,9 +70,8 @@ public class JwtTokenManager {
|
||||
validity = new Date(now + authConfigs.getTokenValidityInSeconds() * 1000L);
|
||||
|
||||
Claims claims = Jwts.claims().setSubject(userName);
|
||||
|
||||
return Jwts.builder().setClaims(claims).setExpiration(validity)
|
||||
.signWith(SignatureAlgorithm.HS256, authConfigs.getSecretKey()).compact();
|
||||
.signWith(Keys.hmacShaKeyFor(authConfigs.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,8 +81,8 @@ public class JwtTokenManager {
|
||||
* @return auth info
|
||||
*/
|
||||
public Authentication getAuthentication(String token) {
|
||||
|
||||
Claims claims = Jwts.parser().setSigningKey(authConfigs.getSecretKey()).parseClaimsJws(token).getBody();
|
||||
Claims claims = Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build()
|
||||
.parseClaimsJws(token).getBody();
|
||||
|
||||
List<GrantedAuthority> authorities = AuthorityUtils
|
||||
.commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES_KEY));
|
||||
@ -97,6 +97,7 @@ public class JwtTokenManager {
|
||||
* @param token token
|
||||
*/
|
||||
public void validateToken(String token) {
|
||||
Jwts.parser().setSigningKey(authConfigs.getSecretKey()).parseClaimsJws(token);
|
||||
Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build().parseClaimsJws(token);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
package com.alibaba.nacos.console.security.nacos;
|
||||
|
||||
import com.alibaba.nacos.auth.common.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.common.AuthSystemTypes;
|
||||
import com.alibaba.nacos.console.filter.JwtAuthenticationTokenFilter;
|
||||
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.core.auth.AuthConfigs;
|
||||
import com.alibaba.nacos.core.auth.AuthSystemTypes;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -17,13 +17,14 @@
|
||||
package com.alibaba.nacos.console.security.nacos;
|
||||
|
||||
import com.alibaba.nacos.api.common.Constants;
|
||||
import com.alibaba.nacos.auth.AuthManager;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.auth.model.Permission;
|
||||
import com.alibaba.nacos.auth.model.User;
|
||||
import com.alibaba.nacos.config.server.auth.RoleInfo;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.console.security.nacos.users.NacosUser;
|
||||
import com.alibaba.nacos.core.auth.AccessException;
|
||||
import com.alibaba.nacos.core.auth.AuthManager;
|
||||
import com.alibaba.nacos.core.auth.Permission;
|
||||
import com.alibaba.nacos.core.auth.User;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -90,7 +91,7 @@ public class NacosAuthManager implements AuthManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req.setAttribute(RequestUtil.NACOS_USER_KEY, user);
|
||||
return user;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.console.security.nacos.roles;
|
||||
|
||||
import com.alibaba.nacos.auth.common.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.model.Permission;
|
||||
import com.alibaba.nacos.config.server.auth.PermissionInfo;
|
||||
import com.alibaba.nacos.config.server.auth.PermissionPersistService;
|
||||
import com.alibaba.nacos.config.server.auth.RoleInfo;
|
||||
@ -23,8 +25,6 @@ import com.alibaba.nacos.config.server.auth.RolePersistService;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
|
||||
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.core.auth.AuthConfigs;
|
||||
import com.alibaba.nacos.core.auth.Permission;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import io.jsonwebtoken.lang.Collections;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -235,4 +235,8 @@ public class NacosRoleServiceImpl {
|
||||
public void deletePermission(String role, String resource, String action) {
|
||||
permissionPersistService.deletePermission(role, resource, action);
|
||||
}
|
||||
|
||||
public List<String> findRolesLikeRoleName(String role) {
|
||||
return rolePersistService.findRolesLikeRoleName(role);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.console.security.nacos.users;
|
||||
|
||||
import com.alibaba.nacos.core.auth.User;
|
||||
import com.alibaba.nacos.auth.model.User;
|
||||
|
||||
/**
|
||||
* Nacos User.
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
package com.alibaba.nacos.console.security.nacos.users;
|
||||
|
||||
import com.alibaba.nacos.auth.common.AuthConfigs;
|
||||
import com.alibaba.nacos.config.server.auth.UserPersistService;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.model.User;
|
||||
import com.alibaba.nacos.core.auth.AuthConfigs;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
@ -28,6 +28,7 @@ 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;
|
||||
|
||||
@ -99,7 +100,11 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService {
|
||||
public User getUserFromDatabase(String username) {
|
||||
return userPersistService.findUserByUsername(username);
|
||||
}
|
||||
|
||||
|
||||
public List<String> findUserLikeUsername(String username) {
|
||||
return userPersistService.findUserLikeUsername(username);
|
||||
}
|
||||
|
||||
public void createUser(String username, String password) {
|
||||
userPersistService.createUser(username, password);
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.MalformedJwtException;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.SignatureException;
|
||||
import io.jsonwebtoken.UnsupportedJwtException;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import io.jsonwebtoken.security.SecurityException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -127,9 +127,7 @@ public class JwtTokenUtils {
|
||||
* @return auth info
|
||||
*/
|
||||
public Authentication getAuthentication(String token) {
|
||||
|
||||
Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
|
||||
|
||||
Claims claims = Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token).getBody();
|
||||
List<GrantedAuthority> authorities = AuthorityUtils
|
||||
.commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES_KEY));
|
||||
|
||||
@ -145,9 +143,9 @@ public class JwtTokenUtils {
|
||||
*/
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
|
||||
Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token);
|
||||
return true;
|
||||
} catch (SignatureException e) {
|
||||
} catch (SecurityException e) {
|
||||
log.info("Invalid JWT signature.");
|
||||
log.trace("Invalid JWT signature trace: {}", e);
|
||||
} catch (MalformedJwtException e) {
|
||||
|
@ -29,7 +29,7 @@ server.port=8848
|
||||
|
||||
|
||||
#*************** Config Module Related Configurations ***************#
|
||||
### If user MySQL as datasource:
|
||||
### If use MySQL as datasource:
|
||||
# spring.datasource.platform=mysql
|
||||
|
||||
### Count of DB:
|
||||
@ -37,8 +37,8 @@ server.port=8848
|
||||
|
||||
### 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=root
|
||||
# db.password=1017
|
||||
# db.user=nacos
|
||||
# db.password=nacos
|
||||
|
||||
|
||||
#*************** Naming Module Related Configurations ***************#
|
||||
@ -154,6 +154,12 @@ nacos.istio.mcp.server.enabled=false
|
||||
## 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 ***************#
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@ -23,7 +23,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Nacos</title>
|
||||
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
|
||||
<link rel="shortcut icon" href="img/nacos-logo.png" type="image/x-icon" />
|
||||
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/console1412.css">
|
||||
<!-- 第三方css开始 -->
|
||||
|
@ -38,3 +38,5 @@ export const PERMISSIONS_LIST = 'PERMISSIONS_LIST';
|
||||
export const GET_NAMESPACES = 'GET_NAMESPACES';
|
||||
|
||||
export const GET_CONFIGURATION = 'GET_CONFIGURATION';
|
||||
|
||||
export const GLOBAL_PAGE_SIZE_LIST = [10, 20, 30, 50, 100];
|
||||
|
@ -74,7 +74,9 @@ class Header extends React.Component {
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
indexAction = () => {
|
||||
this.props.history.push('/');
|
||||
};
|
||||
render() {
|
||||
const {
|
||||
locale = {},
|
||||
@ -94,11 +96,7 @@ class Header extends React.Component {
|
||||
<>
|
||||
<header className="header-container header-container-primary">
|
||||
<div className="header-body">
|
||||
<a
|
||||
href={`https://nacos.io/${language.toLocaleLowerCase()}/`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<a href="#" onClick={this.indexAction} rel="noopener noreferrer">
|
||||
<img
|
||||
src="img/logo-2000-390.svg"
|
||||
className="logo"
|
||||
|
@ -58,7 +58,6 @@ request.middleWare((_config = {}) => {
|
||||
if (res.code === 403 && !hasAlert) {
|
||||
hasAlert = true;
|
||||
window.Dialog.alert({
|
||||
language: aliwareIntl.currentLanguageCode || 'zh-cn',
|
||||
style: { width: 400 },
|
||||
content: res.message,
|
||||
onOk: () => {
|
||||
@ -81,7 +80,6 @@ request.middleWare((_config = {}) => {
|
||||
hasAlert = true;
|
||||
|
||||
window.Dialog.alert({
|
||||
language: aliwareIntl.currentLanguageCode || 'zh-cn',
|
||||
style: { width: 400 },
|
||||
content: aliwareIntl.get('com.alibaba.nacos.pubshow'), // '子账号没有权限,请联系主账号负责人RAM上授权',
|
||||
onOk: () => {
|
||||
|
@ -94,6 +94,7 @@ const I18N_CONF = {
|
||||
namespaceNames: 'Namespaces',
|
||||
namespaceNumber: 'Namespace ID',
|
||||
namespaceOperation: 'Actions',
|
||||
refresh: 'Refresh',
|
||||
},
|
||||
ServiceList: {
|
||||
serviceList: 'Service List',
|
||||
@ -222,6 +223,7 @@ const I18N_CONF = {
|
||||
queryResult: 'Search Results: Found',
|
||||
articleMeet: 'configuration items.',
|
||||
lastUpdateTime: 'Last Modified At',
|
||||
operator: 'Operator',
|
||||
operation: 'Operation',
|
||||
},
|
||||
HistoryDetail: {
|
||||
@ -233,6 +235,7 @@ const I18N_CONF = {
|
||||
moreAdvancedOptions: 'Advanced Options',
|
||||
home: 'Application:',
|
||||
actionType: 'Action Type:',
|
||||
operator: 'Operator:',
|
||||
configureContent: 'Configuration Content:',
|
||||
back: 'Back',
|
||||
},
|
||||
@ -306,6 +309,7 @@ const I18N_CONF = {
|
||||
cloneSuccEnd: 'configuration items cloned',
|
||||
cloneFail: 'Clone failed',
|
||||
getNamespaceFailed: 'get the namespace failed',
|
||||
getNamespace403: 'Without permission to access ${namespaceName} namespace!',
|
||||
startCloning: 'Start Clone',
|
||||
cloningConfiguration: 'Clone config',
|
||||
source: 'Source :',
|
||||
@ -319,6 +323,7 @@ const I18N_CONF = {
|
||||
delSelectedAlertContent: 'please select the configuration to delete',
|
||||
delSuccessMsg: 'delete successful',
|
||||
cloneEditableTitle: 'Modify Data Id and Group (optional)',
|
||||
authFail: 'Auth failed',
|
||||
},
|
||||
NewConfig: {
|
||||
newListingMain: 'Create Configuration',
|
||||
@ -519,6 +524,7 @@ const I18N_CONF = {
|
||||
username: 'Username',
|
||||
password: 'Password',
|
||||
operation: 'Operation',
|
||||
refresh: 'Refresh',
|
||||
},
|
||||
NewUser: {
|
||||
createUser: 'Create user',
|
||||
@ -552,6 +558,7 @@ const I18N_CONF = {
|
||||
operation: 'Operation',
|
||||
deleteRole: 'Delete',
|
||||
deleteRoleTip: 'Do you want to delete this role?',
|
||||
refresh: 'Refresh',
|
||||
},
|
||||
NewRole: {
|
||||
bindingRoles: 'Binding roles',
|
||||
@ -574,6 +581,7 @@ const I18N_CONF = {
|
||||
readOnly: 'read only',
|
||||
writeOnly: 'write only',
|
||||
readWrite: 'Read and write',
|
||||
refresh: 'Refresh',
|
||||
},
|
||||
NewPermissions: {
|
||||
addPermission: 'Add Permission',
|
||||
|
@ -94,6 +94,7 @@ const I18N_CONF = {
|
||||
namespaceNames: '命名空间名称',
|
||||
namespaceNumber: '命名空间ID',
|
||||
namespaceOperation: '操作',
|
||||
refresh: '刷新',
|
||||
},
|
||||
ServiceList: {
|
||||
serviceList: '服务列表',
|
||||
@ -222,6 +223,7 @@ const I18N_CONF = {
|
||||
queryResult: '查询结果:共查询到',
|
||||
articleMeet: '条满足要求的配置。',
|
||||
lastUpdateTime: '最后更新时间',
|
||||
operator: '操作人',
|
||||
operation: '操作',
|
||||
},
|
||||
HistoryDetail: {
|
||||
@ -234,6 +236,7 @@ const I18N_CONF = {
|
||||
home: '归属应用:',
|
||||
actionType: '操作类型:',
|
||||
configureContent: '配置内容:',
|
||||
operator: '操作人:',
|
||||
back: '返回',
|
||||
},
|
||||
DashboardCard: {
|
||||
@ -304,6 +307,7 @@ const I18N_CONF = {
|
||||
cloneSuccEnd: '项配置',
|
||||
cloneFail: '克隆失败',
|
||||
getNamespaceFailed: '获取命名空间失败',
|
||||
getNamespace403: '没有 ${namespaceName} 命名空间的访问权限!',
|
||||
startCloning: '开始克隆',
|
||||
cloningConfiguration: '克隆配置',
|
||||
source: '源空间:',
|
||||
@ -317,6 +321,7 @@ const I18N_CONF = {
|
||||
delSelectedAlertContent: '请选择要删除的配置',
|
||||
delSuccessMsg: '删除成功',
|
||||
cloneEditableTitle: '修改 Data Id 和 Group (可选操作)',
|
||||
authFail: '权限认证失败',
|
||||
},
|
||||
NewConfig: {
|
||||
newListingMain: '新建配置',
|
||||
@ -516,6 +521,7 @@ const I18N_CONF = {
|
||||
username: '用户名',
|
||||
password: '密码',
|
||||
operation: '操作',
|
||||
refresh: '刷新',
|
||||
},
|
||||
NewUser: {
|
||||
createUser: '创建用户',
|
||||
@ -549,6 +555,7 @@ const I18N_CONF = {
|
||||
operation: '操作',
|
||||
deleteRole: '删除',
|
||||
deleteRoleTip: '是否要删除该角色?',
|
||||
refresh: '刷新',
|
||||
},
|
||||
NewRole: {
|
||||
bindingRoles: '绑定角色',
|
||||
@ -571,6 +578,7 @@ const I18N_CONF = {
|
||||
readOnly: '只读',
|
||||
writeOnly: '只写',
|
||||
readWrite: '读写',
|
||||
refresh: '刷新',
|
||||
},
|
||||
NewPermissions: {
|
||||
addPermission: '添加权限',
|
||||
|
@ -19,6 +19,7 @@ import PropTypes from 'prop-types';
|
||||
import { Field, Form, Input, Select, Dialog, ConfigProvider } from '@alifd/next';
|
||||
import { connect } from 'react-redux';
|
||||
import { getNamespaces } from '../../../reducers/namespace';
|
||||
import { searchRoles } from '../../../reducers/authority';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { Option } = Select;
|
||||
@ -28,7 +29,7 @@ const formItemLayout = {
|
||||
wrapperCol: { span: 19 },
|
||||
};
|
||||
|
||||
@connect(state => ({ namespaces: state.namespace.namespaces }), { getNamespaces })
|
||||
@connect(state => ({ namespaces: state.namespace.namespaces }), { getNamespaces, searchRoles })
|
||||
@ConfigProvider.config
|
||||
class NewPermissions extends React.Component {
|
||||
static displayName = 'NewPermissions';
|
||||
@ -39,11 +40,15 @@ class NewPermissions extends React.Component {
|
||||
locale: PropTypes.object,
|
||||
visible: PropTypes.bool,
|
||||
getNamespaces: PropTypes.func,
|
||||
getRoles: PropTypes.func,
|
||||
onOk: PropTypes.func,
|
||||
onCancel: PropTypes.func,
|
||||
namespaces: PropTypes.array,
|
||||
};
|
||||
|
||||
state = {
|
||||
dataSource: [],
|
||||
};
|
||||
componentDidMount() {
|
||||
this.props.getNamespaces();
|
||||
}
|
||||
@ -68,6 +73,14 @@ class NewPermissions extends React.Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
handleChange = value => {
|
||||
if (value.length > 0) {
|
||||
searchRoles(value).then(val => {
|
||||
this.setState({ dataSource: val });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { getError } = this.field;
|
||||
const { visible, onOk, onCancel, locale, namespaces } = this.props;
|
||||
@ -88,7 +101,14 @@ class NewPermissions extends React.Component {
|
||||
>
|
||||
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
|
||||
<FormItem label={locale.role} required help={getError('role')}>
|
||||
<Input name="role" trim placeholder={locale.rolePlaceholder} />
|
||||
<Select.AutoComplete
|
||||
name="role"
|
||||
style={{ width: 316 }}
|
||||
filterLocal={false}
|
||||
placeholder={locale.rolePlaceholder}
|
||||
onChange={this.handleChange}
|
||||
dataSource={this.state.dataSource}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label={locale.resource} required help={getError('resource')}>
|
||||
<Select
|
||||
|
@ -60,6 +60,7 @@ class PermissionsManagement extends React.Component {
|
||||
}
|
||||
|
||||
getPermissions() {
|
||||
this.setState({ loading: true });
|
||||
const { pageNo, pageSize } = this.state;
|
||||
this.props
|
||||
.getPermissions({ pageNo, pageSize })
|
||||
@ -94,6 +95,9 @@ class PermissionsManagement extends React.Component {
|
||||
<Button type="primary" onClick={() => this.setState({ createPermissionVisible: true })}>
|
||||
{locale.addPermission}
|
||||
</Button>
|
||||
<Button type="secondary" onClick={() => this.getPermissions()}>
|
||||
{locale.refresh}
|
||||
</Button>
|
||||
</div>
|
||||
<Table dataSource={permissions.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
|
||||
<Table.Column title={locale.role} dataIndex="role" />
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Field, Form, Input, Dialog, ConfigProvider } from '@alifd/next';
|
||||
import { connect } from 'react-redux';
|
||||
import { Field, Form, Input, Dialog, ConfigProvider, Select } from '@alifd/next';
|
||||
import { searchUsers } from '../../../reducers/authority';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
@ -24,7 +26,7 @@ const formItemLayout = {
|
||||
labelCol: { fixedSpan: 4 },
|
||||
wrapperCol: { span: 19 },
|
||||
};
|
||||
|
||||
@connect(state => ({ users: state.authority.users }), { searchUsers })
|
||||
@ConfigProvider.config
|
||||
class NewRole extends React.Component {
|
||||
static displayName = 'NewRole';
|
||||
@ -35,9 +37,14 @@ class NewRole extends React.Component {
|
||||
locale: PropTypes.object,
|
||||
visible: PropTypes.bool,
|
||||
onOk: PropTypes.func,
|
||||
getUsers: PropTypes.func,
|
||||
onCancel: PropTypes.func,
|
||||
};
|
||||
|
||||
state = {
|
||||
dataSource: [],
|
||||
};
|
||||
|
||||
check() {
|
||||
const { locale } = this.props;
|
||||
const errors = {
|
||||
@ -57,6 +64,14 @@ class NewRole extends React.Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
handleChange = value => {
|
||||
if (value.length > 0) {
|
||||
searchUsers(value).then(val => {
|
||||
this.setState({ dataSource: val });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { locale } = this.props;
|
||||
const { getError } = this.field;
|
||||
@ -81,7 +96,14 @@ class NewRole extends React.Component {
|
||||
<Input name="role" trim placeholder={locale.rolePlaceholder} />
|
||||
</FormItem>
|
||||
<FormItem label={locale.username} required help={getError('username')}>
|
||||
<Input name="username" placeholder={locale.usernamePlaceholder} />
|
||||
<Select.AutoComplete
|
||||
name="username"
|
||||
style={{ width: 316 }}
|
||||
filterLocal={false}
|
||||
placeholder={locale.usernamePlaceholder}
|
||||
onChange={this.handleChange}
|
||||
dataSource={this.state.dataSource}
|
||||
/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Dialog>
|
||||
|
@ -49,6 +49,7 @@ class RolesManagement extends React.Component {
|
||||
}
|
||||
|
||||
getRoles() {
|
||||
this.setState({ loading: true });
|
||||
const { pageNo, pageSize } = this.state;
|
||||
this.props
|
||||
.getRoles({ pageNo, pageSize })
|
||||
@ -74,6 +75,9 @@ class RolesManagement extends React.Component {
|
||||
<Button type="primary" onClick={() => this.setState({ createRoleVisible: true })}>
|
||||
{locale.bindingRoles}
|
||||
</Button>
|
||||
<Button type="secondary" onClick={() => this.getRoles()}>
|
||||
{locale.refresh}
|
||||
</Button>
|
||||
</div>
|
||||
<Table dataSource={roles.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
|
||||
<Table.Column title={locale.role} dataIndex="role" />
|
||||
|
@ -51,6 +51,7 @@ class UserManagement extends React.Component {
|
||||
}
|
||||
|
||||
getUsers() {
|
||||
this.setState({ loading: true });
|
||||
const { pageNo, pageSize } = this.state;
|
||||
this.props
|
||||
.getUsers({ pageNo, pageSize })
|
||||
@ -76,6 +77,9 @@ class UserManagement extends React.Component {
|
||||
<Button type="primary" onClick={() => this.setState({ createUserVisible: true })}>
|
||||
{locale.createUser}
|
||||
</Button>
|
||||
<Button type="secondary" onClick={() => this.getUsers()}>
|
||||
{locale.refresh}
|
||||
</Button>
|
||||
</div>
|
||||
<Table dataSource={users.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
|
||||
<Table.Column title={locale.username} dataIndex="username" />
|
||||
|
@ -134,6 +134,8 @@ class ConfigDetail extends React.Component {
|
||||
self.field.setValue('config_tags', data.configTags);
|
||||
self.field.setValue('desc', data.desc);
|
||||
self.field.setValue('md5', data.md5);
|
||||
self.field.setValue('type', data.type);
|
||||
self.initMoacoEditor(data.type, data.content);
|
||||
} else {
|
||||
Dialog.alert({ title: locale.error, content: result.message });
|
||||
}
|
||||
@ -157,6 +159,35 @@ class ConfigDetail extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
initMoacoEditor(language, value) {
|
||||
const container = document.getElementById('container');
|
||||
container.innerHTML = '';
|
||||
this.monacoEditor = null;
|
||||
const options = {
|
||||
value,
|
||||
language,
|
||||
codeLens: true,
|
||||
selectOnLineNumbers: true,
|
||||
roundedSelection: false,
|
||||
readOnly: true,
|
||||
lineNumbersMinChars: true,
|
||||
theme: 'vs-dark',
|
||||
wordWrapColumn: 120,
|
||||
folding: false,
|
||||
showFoldingControls: 'always',
|
||||
wordWrap: 'wordWrapColumn',
|
||||
cursorStyle: 'line',
|
||||
automaticLayout: true,
|
||||
};
|
||||
if (!window.monaco) {
|
||||
window.importEditor(() => {
|
||||
this.monacoEditor = window.monaco.editor.create(container, options);
|
||||
});
|
||||
} else {
|
||||
this.monacoEditor = window.monaco.editor.create(container, options);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { locale = {} } = this.props;
|
||||
const { init } = this.field;
|
||||
@ -243,7 +274,7 @@ class ConfigDetail extends React.Component {
|
||||
<Input htmlType={'text'} readOnly {...init('md5')} />
|
||||
</FormItem>
|
||||
<FormItem label={locale.configuration} required {...formItemLayout}>
|
||||
<Input.TextArea htmlType={'text'} multiple rows={15} readOnly {...init('content')} />
|
||||
<div style={{ clear: 'both', height: 300 }} id="container" />
|
||||
</FormItem>
|
||||
<FormItem label={' '} {...formItemLayout}>
|
||||
<Button type={'primary'} onClick={this.goList.bind(this)}>
|
||||
|
@ -46,7 +46,7 @@ import { connect } from 'react-redux';
|
||||
import { getConfigs } from '../../../reducers/configuration';
|
||||
|
||||
import './index.scss';
|
||||
import { LANGUAGE_KEY } from '../../../constants';
|
||||
import { LANGUAGE_KEY, GLOBAL_PAGE_SIZE_LIST } from '../../../constants';
|
||||
|
||||
const { Panel } = Collapse;
|
||||
const configsTableSelected = new Map();
|
||||
@ -250,6 +250,7 @@ class ConfigurationManagement extends React.Component {
|
||||
if (this.state.loading) {
|
||||
return;
|
||||
}
|
||||
const { locale = {}, configurations = {} } = this.props;
|
||||
this.tenant = getParams('namespace') || ''; // 为当前实例保存tenant参数
|
||||
this.serverId = getParams('serverId') || '';
|
||||
const prePageNo = getParams('pageNo');
|
||||
@ -273,14 +274,32 @@ class ConfigurationManagement extends React.Component {
|
||||
params.search = 'accurate';
|
||||
}
|
||||
this.setState({ loading: true });
|
||||
this.props.getConfigs(params).then(() =>
|
||||
this.setState({
|
||||
loading: false,
|
||||
selectedRecord: [],
|
||||
selectedKeys: [],
|
||||
tenant: this.tenant,
|
||||
})
|
||||
);
|
||||
this.props
|
||||
.getConfigs(params)
|
||||
.then(() =>
|
||||
this.setState({
|
||||
loading: false,
|
||||
selectedRecord: [],
|
||||
selectedKeys: [],
|
||||
tenant: this.tenant,
|
||||
})
|
||||
)
|
||||
.catch(res => {
|
||||
configurations.pageItems = [];
|
||||
configurations.totalCount = 0;
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
if (res && [401, 403].includes(res.status)) {
|
||||
Dialog.alert({
|
||||
title: locale.authFail,
|
||||
content: locale.getNamespace403.replace(
|
||||
'${namespaceName}',
|
||||
this.state.nownamespace_name
|
||||
),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showMore() {}
|
||||
@ -1384,7 +1403,7 @@ class ConfigurationManagement extends React.Component {
|
||||
</div>
|
||||
<Pagination
|
||||
style={{ float: 'right' }}
|
||||
pageSizeList={[10, 20, 30]}
|
||||
pageSizeList={GLOBAL_PAGE_SIZE_LIST}
|
||||
pageSizePosition="start"
|
||||
pageSizeSelector="dropdown"
|
||||
popupProps={{ align: 'bl tl' }}
|
||||
|
@ -74,6 +74,7 @@ class HistoryDetail extends React.Component {
|
||||
self.field.setValue('content', data.content);
|
||||
self.field.setValue('appName', self.inApp ? self.edasAppName : data.appName);
|
||||
self.field.setValue('envs', self.serverId);
|
||||
self.field.setValue('srcUser', self.srcUser);
|
||||
self.field.setValue('opType', typeMap[data.opType.trim()]);
|
||||
self.field.setValue('group', data.group);
|
||||
self.field.setValue('md5', data.md5);
|
||||
@ -119,6 +120,9 @@ class HistoryDetail extends React.Component {
|
||||
<Input htmlType="text" readOnly {...init('appName')} />
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item label={locale.operator} required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('srcUser')} />
|
||||
</Form.Item>
|
||||
<Form.Item label={locale.actionType} required {...formItemLayout}>
|
||||
<Input htmlType="text" readOnly {...init('opType')} />
|
||||
</Form.Item>
|
||||
|
@ -293,6 +293,7 @@ class HistoryRollback extends React.Component {
|
||||
<Table dataSource={this.state.dataSource} locale={{ empty: locale.pubNoData }}>
|
||||
<Table.Column title="Data ID" dataIndex="dataId" />
|
||||
<Table.Column title="Group" dataIndex="group" />
|
||||
<Table.Column title={locale.operator} dataIndex="srcUser" />
|
||||
<Table.Column
|
||||
title={locale.lastUpdateTime}
|
||||
dataIndex="lastModifiedTime"
|
||||
|
@ -266,7 +266,6 @@ class NewConfig extends React.Component {
|
||||
} else {
|
||||
Dialog.confirm({
|
||||
content: locale.confirmSyanx,
|
||||
language: aliwareIntl.currentLanguageCode || 'zh-cn',
|
||||
onOk: () => {
|
||||
this.publicConfigBeforeCheck(content);
|
||||
},
|
||||
@ -352,7 +351,6 @@ class NewConfig extends React.Component {
|
||||
error: res => {
|
||||
this.closeLoading();
|
||||
Dialog.alert({
|
||||
language: aliwareIntl.currentLanguageCode || 'zh-cn',
|
||||
content: locale.publishFailed,
|
||||
});
|
||||
},
|
||||
|
@ -47,53 +47,51 @@ class NameSpace extends React.Component {
|
||||
this.getNameSpaces(0);
|
||||
}
|
||||
|
||||
getNameSpaces(delayTime = 2000) {
|
||||
getNameSpaces() {
|
||||
const { locale = {} } = this.props;
|
||||
const { prompt } = locale;
|
||||
const self = this;
|
||||
self.openLoading();
|
||||
setTimeout(() => {
|
||||
request({
|
||||
type: 'get',
|
||||
beforeSend() {},
|
||||
url: 'v1/console/namespaces',
|
||||
success: res => {
|
||||
if (res.code === 200) {
|
||||
const data = res.data || [];
|
||||
window.namespaceList = data;
|
||||
request({
|
||||
type: 'get',
|
||||
beforeSend() {},
|
||||
url: 'v1/console/namespaces',
|
||||
success: res => {
|
||||
if (res.code === 200) {
|
||||
const data = res.data || [];
|
||||
window.namespaceList = data;
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].type === 1) {
|
||||
this.setState({
|
||||
defaultNamespace: data[i].namespace,
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].type === 1) {
|
||||
this.setState({
|
||||
defaultNamespace: data[i].namespace,
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
dataSource: data,
|
||||
});
|
||||
} else {
|
||||
Dialog.alert({
|
||||
title: prompt,
|
||||
content: res.message,
|
||||
});
|
||||
}
|
||||
},
|
||||
complete() {
|
||||
self.closeLoading();
|
||||
},
|
||||
error: res => {
|
||||
window.namespaceList = [
|
||||
{
|
||||
namespace: '',
|
||||
namespaceShowName: '公共空间',
|
||||
type: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
}, delayTime);
|
||||
|
||||
this.setState({
|
||||
dataSource: data,
|
||||
});
|
||||
} else {
|
||||
Dialog.alert({
|
||||
title: prompt,
|
||||
content: res.message,
|
||||
});
|
||||
}
|
||||
},
|
||||
complete() {
|
||||
self.closeLoading();
|
||||
},
|
||||
error: res => {
|
||||
window.namespaceList = [
|
||||
{
|
||||
namespace: '',
|
||||
namespaceShowName: '公共空间',
|
||||
type: 0,
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
openLoading() {
|
||||
@ -315,6 +313,13 @@ class NameSpace extends React.Component {
|
||||
>
|
||||
{namespaceAdd}
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginRight: 0, marginTop: 10 }}
|
||||
type="secondary"
|
||||
onClick={() => this.getNameSpaces()}
|
||||
>
|
||||
{locale.refresh}
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Table dataSource={this.state.dataSource} locale={{ empty: pubNoData }}>
|
||||
|
@ -37,6 +37,7 @@ import EditServiceDialog from '../ServiceDetail/EditServiceDialog';
|
||||
import ShowServiceCodeing from 'components/ShowCodeing/ShowServiceCodeing';
|
||||
|
||||
import './ServiceList.scss';
|
||||
import { GLOBAL_PAGE_SIZE_LIST } from '../../../constants';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { Row, Col } = Grid;
|
||||
@ -94,12 +95,14 @@ class ServiceList extends React.Component {
|
||||
`serviceNameParam=${search.serviceName}`,
|
||||
`groupNameParam=${search.groupName}`,
|
||||
];
|
||||
this.openLoading();
|
||||
request({
|
||||
url: `v1/ns/catalog/services?${parameter.join('&')}`,
|
||||
success: ({ count = 0, serviceList = [] } = {}) => {
|
||||
this.setState({
|
||||
dataSource: serviceList,
|
||||
total: count,
|
||||
loading: false,
|
||||
});
|
||||
},
|
||||
error: () =>
|
||||
@ -107,6 +110,7 @@ class ServiceList extends React.Component {
|
||||
dataSource: [],
|
||||
total: 0,
|
||||
currentPage: 0,
|
||||
loading: false,
|
||||
}),
|
||||
});
|
||||
}
|
||||
@ -129,6 +133,10 @@ class ServiceList extends React.Component {
|
||||
this.showcode.current.getInstance().openDialog(record);
|
||||
}
|
||||
|
||||
handlePageSizeChange(pageSize) {
|
||||
this.setState({ pageSize }, () => this.queryServiceList());
|
||||
}
|
||||
|
||||
deleteService(service) {
|
||||
const { locale = {} } = this.props;
|
||||
const { prompt, promptDelete } = locale;
|
||||
@ -187,156 +195,143 @@ class ServiceList extends React.Component {
|
||||
|
||||
return (
|
||||
<div className="main-container service-management">
|
||||
<Loading
|
||||
shape="flower"
|
||||
<div style={{ marginTop: -15 }}>
|
||||
<RegionGroup
|
||||
setNowNameSpace={this.setNowNameSpace}
|
||||
namespaceCallBack={this.getQueryLater}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="page-title">
|
||||
<span className="title-item">{serviceList}</span>
|
||||
<span className="title-item">|</span>
|
||||
<span className="title-item">{nowNamespaceName}</span>
|
||||
<span className="title-item">{nowNamespaceId}</span>
|
||||
</h3>
|
||||
<Row
|
||||
className="demo-row"
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
marginBottom: 10,
|
||||
padding: 0,
|
||||
}}
|
||||
visible={this.state.loading}
|
||||
tip="Loading..."
|
||||
color="#333"
|
||||
>
|
||||
<div style={{ marginTop: -15 }}>
|
||||
<RegionGroup
|
||||
setNowNameSpace={this.setNowNameSpace}
|
||||
namespaceCallBack={this.getQueryLater}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="page-title">
|
||||
<span className="title-item">{serviceList}</span>
|
||||
<span className="title-item">|</span>
|
||||
<span className="title-item">{nowNamespaceName}</span>
|
||||
<span className="title-item">{nowNamespaceId}</span>
|
||||
</h3>
|
||||
<Row
|
||||
className="demo-row"
|
||||
style={{
|
||||
marginBottom: 10,
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
<Col span="24">
|
||||
<Form inline field={this.field}>
|
||||
<FormItem label={serviceName}>
|
||||
<Input
|
||||
placeholder={serviceNamePlaceholder}
|
||||
style={{ width: 200 }}
|
||||
value={search.serviceName}
|
||||
onChange={serviceName => this.setState({ search: { ...search, serviceName } })}
|
||||
onPressEnter={() =>
|
||||
this.setState({ currentPage: 1 }, () => this.queryServiceList())
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label={groupName}>
|
||||
<Input
|
||||
placeholder={groupNamePlaceholder}
|
||||
style={{ width: 200 }}
|
||||
value={search.groupName}
|
||||
onChange={groupName => this.setState({ search: { ...search, groupName } })}
|
||||
onPressEnter={() =>
|
||||
this.setState({ currentPage: 1 }, () => this.queryServiceList())
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
<Form.Item label={`${hiddenEmptyService}:`}>
|
||||
<Switch
|
||||
checked={hasIpCount}
|
||||
onChange={hasIpCount =>
|
||||
this.setState({ hasIpCount, currentPage: 1 }, () => {
|
||||
localStorage.setItem('hasIpCount', hasIpCount);
|
||||
this.queryServiceList();
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
<FormItem label="">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => this.setState({ currentPage: 1 }, () => this.queryServiceList())}
|
||||
style={{ marginRight: 10 }}
|
||||
>
|
||||
{query}
|
||||
</Button>
|
||||
</FormItem>
|
||||
<FormItem label="" style={{ float: 'right' }}>
|
||||
<Button type="secondary" onClick={() => this.openEditServiceDialog()}>
|
||||
{create}
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ padding: 0 }}>
|
||||
<Col span="24" style={{ padding: 0 }}>
|
||||
<Table
|
||||
dataSource={this.state.dataSource}
|
||||
locale={{ empty: pubNoData }}
|
||||
getRowProps={row => this.rowColor(row)}
|
||||
>
|
||||
<Column title={locale.columnServiceName} dataIndex="name" />
|
||||
<Column title={locale.groupName} dataIndex="groupName" />
|
||||
<Column title={locale.columnClusterCount} dataIndex="clusterCount" />
|
||||
<Column title={locale.columnIpCount} dataIndex="ipCount" />
|
||||
<Column
|
||||
title={locale.columnHealthyInstanceCount}
|
||||
dataIndex="healthyInstanceCount"
|
||||
<Col span="24">
|
||||
<Form inline field={this.field}>
|
||||
<FormItem label={serviceName}>
|
||||
<Input
|
||||
placeholder={serviceNamePlaceholder}
|
||||
style={{ width: 200 }}
|
||||
value={search.serviceName}
|
||||
onChange={serviceName => this.setState({ search: { ...search, serviceName } })}
|
||||
onPressEnter={() =>
|
||||
this.setState({ currentPage: 1 }, () => this.queryServiceList())
|
||||
}
|
||||
/>
|
||||
<Column title={locale.columnTriggerFlag} dataIndex="triggerFlag" />
|
||||
<Column
|
||||
title={operation}
|
||||
align="center"
|
||||
cell={(value, index, record) => (
|
||||
// @author yongchao9 #2019年05月18日 下午5:46:28
|
||||
/* Add a link to view "sample code"
|
||||
</FormItem>
|
||||
<FormItem label={groupName}>
|
||||
<Input
|
||||
placeholder={groupNamePlaceholder}
|
||||
style={{ width: 200 }}
|
||||
value={search.groupName}
|
||||
onChange={groupName => this.setState({ search: { ...search, groupName } })}
|
||||
onPressEnter={() =>
|
||||
this.setState({ currentPage: 1 }, () => this.queryServiceList())
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
<Form.Item label={`${hiddenEmptyService}:`}>
|
||||
<Switch
|
||||
checked={hasIpCount}
|
||||
onChange={hasIpCount =>
|
||||
this.setState({ hasIpCount, currentPage: 1 }, () => {
|
||||
localStorage.setItem('hasIpCount', hasIpCount);
|
||||
this.queryServiceList();
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
<FormItem label="">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => this.setState({ currentPage: 1 }, () => this.queryServiceList())}
|
||||
style={{ marginRight: 10 }}
|
||||
>
|
||||
{query}
|
||||
</Button>
|
||||
</FormItem>
|
||||
<FormItem label="" style={{ float: 'right' }}>
|
||||
<Button type="secondary" onClick={() => this.openEditServiceDialog()}>
|
||||
{create}
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ padding: 0 }}>
|
||||
<Col span="24" style={{ padding: 0 }}>
|
||||
<Table
|
||||
dataSource={this.state.dataSource}
|
||||
locale={{ empty: pubNoData }}
|
||||
getRowProps={row => this.rowColor(row)}
|
||||
loading={this.state.loading}
|
||||
>
|
||||
<Column title={locale.columnServiceName} dataIndex="name" />
|
||||
<Column title={locale.groupName} dataIndex="groupName" />
|
||||
<Column title={locale.columnClusterCount} dataIndex="clusterCount" />
|
||||
<Column title={locale.columnIpCount} dataIndex="ipCount" />
|
||||
<Column title={locale.columnHealthyInstanceCount} dataIndex="healthyInstanceCount" />
|
||||
<Column title={locale.columnTriggerFlag} dataIndex="triggerFlag" />
|
||||
<Column
|
||||
title={operation}
|
||||
align="center"
|
||||
cell={(value, index, record) => (
|
||||
// @author yongchao9 #2019年05月18日 下午5:46:28
|
||||
/* Add a link to view "sample code"
|
||||
replace the original button with a label,
|
||||
which is consistent with the operation style in configuration management.
|
||||
*/
|
||||
<div>
|
||||
<a
|
||||
onClick={() => {
|
||||
const { name, groupName } = record;
|
||||
this.props.history.push(
|
||||
generateUrl('/serviceDetail', { name, groupName })
|
||||
);
|
||||
}}
|
||||
style={{ marginRight: 5 }}
|
||||
>
|
||||
{detail}
|
||||
</a>
|
||||
<span style={{ marginRight: 5 }}>|</span>
|
||||
<a style={{ marginRight: 5 }} onClick={() => this.showSampleCode(record)}>
|
||||
{sampleCode}
|
||||
</a>
|
||||
<span style={{ marginRight: 5 }}>|</span>
|
||||
<a onClick={() => this.deleteService(record)} style={{ marginRight: 5 }}>
|
||||
{deleteAction}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
</Col>
|
||||
</Row>
|
||||
{this.state.total > this.state.pageSize && (
|
||||
<div
|
||||
style={{
|
||||
marginTop: 10,
|
||||
textAlign: 'right',
|
||||
}}
|
||||
>
|
||||
<Pagination
|
||||
current={this.state.currentPage}
|
||||
total={this.state.total}
|
||||
pageSize={this.state.pageSize}
|
||||
onChange={currentPage =>
|
||||
this.setState({ currentPage }, () => this.queryServiceList())
|
||||
}
|
||||
<div>
|
||||
<a
|
||||
onClick={() => {
|
||||
const { name, groupName } = record;
|
||||
this.props.history.push(generateUrl('/serviceDetail', { name, groupName }));
|
||||
}}
|
||||
style={{ marginRight: 5 }}
|
||||
>
|
||||
{detail}
|
||||
</a>
|
||||
<span style={{ marginRight: 5 }}>|</span>
|
||||
<a style={{ marginRight: 5 }} onClick={() => this.showSampleCode(record)}>
|
||||
{sampleCode}
|
||||
</a>
|
||||
<span style={{ marginRight: 5 }}>|</span>
|
||||
<a onClick={() => this.deleteService(record)} style={{ marginRight: 5 }}>
|
||||
{deleteAction}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Loading>
|
||||
</Table>
|
||||
</Col>
|
||||
</Row>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 10,
|
||||
textAlign: 'right',
|
||||
}}
|
||||
>
|
||||
<Pagination
|
||||
current={this.state.currentPage}
|
||||
pageSizeList={GLOBAL_PAGE_SIZE_LIST}
|
||||
pageSizePosition="start"
|
||||
pageSizeSelector="dropdown"
|
||||
popupProps={{ align: 'bl tl' }}
|
||||
total={this.state.total}
|
||||
pageSize={this.state.pageSize}
|
||||
onPageSizeChange={pageSize => this.handlePageSizeChange(pageSize)}
|
||||
onChange={currentPage => this.setState({ currentPage }, () => this.queryServiceList())}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ShowServiceCodeing ref={this.showcode} />
|
||||
<EditServiceDialog
|
||||
ref={this.editServiceDialog}
|
||||
|
@ -60,6 +60,13 @@ const getUsers = params => dispatch =>
|
||||
const createUser = ([username, password]) =>
|
||||
request.post('v1/auth/users', { username, password }).then(res => successMsg(res));
|
||||
|
||||
/**
|
||||
* 通过username 模糊匹配
|
||||
* @param {*} param0
|
||||
*/
|
||||
const searchUsers = username =>
|
||||
request.get('v1/auth/users/search', { params: { username } }).then(res => successMsg(res));
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
* @param {*} username
|
||||
@ -82,6 +89,13 @@ const passwordReset = ([username, newPassword]) =>
|
||||
const getRoles = params => dispatch =>
|
||||
request.get('v1/auth/roles', { params }).then(data => dispatch({ type: ROLE_LIST, data }));
|
||||
|
||||
/**
|
||||
* 通过username 模糊匹配
|
||||
* @param {*} param0
|
||||
*/
|
||||
const searchRoles = role =>
|
||||
request.get('v1/auth/roles/search', { params: { role } }).then(res => successMsg(res));
|
||||
|
||||
/**
|
||||
* 创建角色
|
||||
* @param {*} param0
|
||||
@ -133,10 +147,12 @@ export default (state = initialState, action) => {
|
||||
};
|
||||
|
||||
export {
|
||||
searchUsers,
|
||||
getUsers,
|
||||
createUser,
|
||||
deleteUser,
|
||||
passwordReset,
|
||||
searchRoles,
|
||||
getRoles,
|
||||
createRole,
|
||||
deleteRole,
|
||||
|
@ -16,6 +16,92 @@
|
||||
|
||||
import * as yamljs from 'yamljs';
|
||||
|
||||
/**
|
||||
* 校验一个配置项
|
||||
*/
|
||||
function validateProperty(property) {
|
||||
let { length } = property;
|
||||
let keyLen = 0;
|
||||
let valueStart = length;
|
||||
let hasSep = false;
|
||||
let precedingBackslash = false;
|
||||
let c;
|
||||
// 解析 key
|
||||
while (keyLen < length) {
|
||||
c = property[keyLen];
|
||||
if ((c === '=' || c === ':') && !precedingBackslash) {
|
||||
valueStart = keyLen + 1;
|
||||
hasSep = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((c === ' ' || c === '\t' || c === '\f') && !precedingBackslash) {
|
||||
valueStart = keyLen + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c === '\\') {
|
||||
precedingBackslash = !precedingBackslash;
|
||||
} else {
|
||||
precedingBackslash = false;
|
||||
}
|
||||
keyLen++;
|
||||
}
|
||||
// 解析 value
|
||||
while (valueStart < length) {
|
||||
c = property[valueStart];
|
||||
if (c !== ' ' && c !== '\t' && c !== '\f') {
|
||||
if (!hasSep && (c === '=' || c === ':')) {
|
||||
hasSep = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
valueStart++;
|
||||
}
|
||||
|
||||
return (
|
||||
validateKeyOrValueForProperty(property, 0, keyLen) &&
|
||||
validateKeyOrValueForProperty(property, valueStart, length)
|
||||
);
|
||||
}
|
||||
|
||||
function validateKeyOrValueForProperty(property, start, end) {
|
||||
// check null
|
||||
if (start >= end) {
|
||||
return false;
|
||||
}
|
||||
let index = 0;
|
||||
let c;
|
||||
while (index < property.length) {
|
||||
c = property[index++];
|
||||
if (c !== '\\') {
|
||||
continue;
|
||||
}
|
||||
|
||||
c = property[index++];
|
||||
// check backslash
|
||||
if (!isPropertyEscape(c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check Unicode
|
||||
if (c === 'u') {
|
||||
let unicode = property.slice(index, index + 4).join('');
|
||||
if (unicode.match(/^[a-f0-9]{4}$/i) === null) {
|
||||
return false;
|
||||
}
|
||||
index += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isPropertyEscape(c = '') {
|
||||
return 'abfnrt\\"\'0! #:=u'.includes(c);
|
||||
}
|
||||
|
||||
export default {
|
||||
/**
|
||||
* 检测json是否合法
|
||||
@ -65,12 +151,91 @@ export default {
|
||||
* 检测属性是否正确
|
||||
*/
|
||||
validateProperties(str = '') {
|
||||
const reg = /^[^=]+=.+$/;
|
||||
return str
|
||||
.replace('\n\r', '\n')
|
||||
.split('\n')
|
||||
.filter(_str => _str)
|
||||
.every(_str => reg.test(_str.trim()));
|
||||
let isNewLine = true;
|
||||
let isCommentLine = false;
|
||||
let isSkipWhiteSpace = true;
|
||||
let precedingBackslash = false;
|
||||
let appendedLineBegin = false;
|
||||
let skipLF = false;
|
||||
let hasProperty = false;
|
||||
let property = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let c = str[i];
|
||||
|
||||
if (skipLF) {
|
||||
skipLF = false;
|
||||
if (c === '\n') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 跳过行首空白字符
|
||||
if (isSkipWhiteSpace) {
|
||||
if (c === ' ' || c === '\t' || c === '\f') {
|
||||
continue;
|
||||
}
|
||||
if (!appendedLineBegin && (c === '\r' || c === '\n')) {
|
||||
continue;
|
||||
}
|
||||
appendedLineBegin = false;
|
||||
isSkipWhiteSpace = false;
|
||||
}
|
||||
|
||||
// 判断注释行
|
||||
if (isNewLine) {
|
||||
isNewLine = false;
|
||||
if (c === '#' || c === '!') {
|
||||
isCommentLine = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (c !== '\n' && c !== '\r') {
|
||||
property.push(c);
|
||||
if (c === '\\') {
|
||||
precedingBackslash = !precedingBackslash;
|
||||
} else {
|
||||
precedingBackslash = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 跳过注释行
|
||||
if (isCommentLine || property.length === 0) {
|
||||
isNewLine = true;
|
||||
isCommentLine = false;
|
||||
isSkipWhiteSpace = true;
|
||||
property = [];
|
||||
continue;
|
||||
}
|
||||
|
||||
// 处理转移字符
|
||||
if (precedingBackslash) {
|
||||
property.pop();
|
||||
precedingBackslash = false;
|
||||
isSkipWhiteSpace = true;
|
||||
appendedLineBegin = true;
|
||||
if (c === '\r') {
|
||||
skipLF = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 解析出配置项
|
||||
// 进行校验
|
||||
if (!validateProperty(property)) {
|
||||
return false;
|
||||
}
|
||||
hasProperty = true;
|
||||
property = [];
|
||||
isNewLine = true;
|
||||
isSkipWhiteSpace = true;
|
||||
}
|
||||
|
||||
// 校验最后一行
|
||||
if (property.length > 0 && !isCommentLine) {
|
||||
return validateProperty(property);
|
||||
}
|
||||
|
||||
return hasProperty;
|
||||
},
|
||||
|
||||
/**
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -16,11 +16,11 @@
|
||||
|
||||
package com.alibaba.nacos.console.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.common.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.common.AuthSystemTypes;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.console.security.nacos.NacosAuthManager;
|
||||
import com.alibaba.nacos.console.security.nacos.users.NacosUser;
|
||||
import com.alibaba.nacos.core.auth.AccessException;
|
||||
import com.alibaba.nacos.core.auth.AuthConfigs;
|
||||
import com.alibaba.nacos.core.auth.AuthSystemTypes;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user