From f5aa648c51f3c81140558d3da722f0977f6d2577 Mon Sep 17 00:00:00 2001
From: xuekang <914468783@qq.com>
Date: 星期五, 10 五月 2024 20:46:38 +0800
Subject: [PATCH] 初始化

---
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/config/ConsoleConfig.java                |   82 +++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java    |   55 ++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java   |   64 ++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/Nacos.java                                       |   44 ++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/NacosApiExceptionHandler.java  |  131 +++++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/NamespaceAllInfo.java              |   31 +
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java |  152 ++++++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java      |  155 +++++++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/form/NamespaceForm.java            |  111 +++++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/filter/XssFilter.java                    |   44 ++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java   |  150 ++++++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/enums/NamespaceTypeEnum.java             |   66 +++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/HealthController.java         |  110 +++++
 ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/Namespace.java                     |  115 +++++
 14 files changed, 1,310 insertions(+), 0 deletions(-)

diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/Nacos.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/Nacos.java
new file mode 100644
index 0000000..61a6f81
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/Nacos.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * Nacos starter.
+ *
+ * @author nacos
+ */
+@SpringBootApplication(scanBasePackages = "com.alibaba.nacos")
+@ServletComponentScan
+@EnableScheduling
+public class Nacos {
+
+    public static void main(String[] args) {
+        // true 鍗曟満妯″紡 false 涓洪泦缇ゆā寮� 闆嗙兢妯″紡闇�鎼厤 cluster.conf 浣跨敤 浣跨敤鏂规硶璇锋煡鐪嬫枃妗�
+        System.setProperty("nacos.standalone", "true");
+        System.setProperty("server.tomcat.accesslog.enabled", "false");
+        // 鏈湴闆嗙兢鎼缓浣跨敤 鍒嗗埆鍦ㄦ墍鏈� nacos 鐩綍涓嬪垱寤� conf/cluster.conf 鏂囦欢鐢ㄤ簬缂栧啓闆嗙兢ip绔彛
+        // 娉ㄦ剰 濡傛灉鏈湴鍚姩澶氫釜 nacos 姝ょ洰褰曚笉鑳界浉鍚� 渚嬪 nacos1 nacos2 nacos3 瀵瑰簲涓変釜nacos鏈嶅姟
+        // System.setProperty("nacos.home", "D:/nacos");
+        SpringApplication.run(Nacos.class, args);
+    }
+}
+
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/config/ConsoleConfig.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/config/ConsoleConfig.java
new file mode 100644
index 0000000..2afdaae
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/config/ConsoleConfig.java
@@ -0,0 +1,82 @@
+/*
+ * 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.console.config;
+
+import com.alibaba.nacos.console.filter.XssFilter;
+import com.alibaba.nacos.core.code.ControllerMethodsCache;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.stereotype.Component;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.annotation.PostConstruct;
+import java.time.ZoneId;
+
+/**
+ * Console config.
+ *
+ * @author yshen
+ * @author nkorange
+ * @since 1.2.0
+ */
+@Component
+@EnableScheduling
+@PropertySource("/application.properties")
+public class ConsoleConfig {
+    
+    @Autowired
+    private ControllerMethodsCache methodsCache;
+    
+    /**
+     * Init.
+     */
+    @PostConstruct
+    public void init() {
+        methodsCache.initClassMethod("com.alibaba.nacos.core.controller");
+        methodsCache.initClassMethod("com.alibaba.nacos.naming.controllers");
+        methodsCache.initClassMethod("com.alibaba.nacos.config.server.controller");
+        methodsCache.initClassMethod("com.alibaba.nacos.console.controller");
+    }
+    
+    @Bean
+    public CorsFilter corsFilter() {
+        CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        config.addAllowedHeader("*");
+        config.setMaxAge(18000L);
+        config.addAllowedMethod("*");
+        config.addAllowedOriginPattern("*");
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
+    
+    @Bean
+    public XssFilter xssFilter() {
+        return new XssFilter();
+    }
+    
+    @Bean
+    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
+        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(ZoneId.systemDefault().toString());
+    }
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/HealthController.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/HealthController.java
new file mode 100644
index 0000000..f5b0e98
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/HealthController.java
@@ -0,0 +1,110 @@
+/*
+ * 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.console.controller;
+
+import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
+import com.alibaba.nacos.naming.controllers.OperatorController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Health Controller.
+ *
+ * @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
+ */
+@RestController("consoleHealth")
+@RequestMapping("/v1/console/health")
+public class HealthController {
+    
+    private static final Logger LOGGER = LoggerFactory.getLogger(HealthController.class);
+    
+    private final ConfigInfoPersistService configInfoPersistService;
+    
+    private final OperatorController apiCommands;
+    
+    @Autowired
+    public HealthController(ConfigInfoPersistService configInfoPersistService, OperatorController apiCommands) {
+        this.configInfoPersistService = configInfoPersistService;
+        this.apiCommands = apiCommands;
+    }
+    
+    /**
+     * Whether the Nacos is in broken states or not, and cannot recover except by being restarted.
+     *
+     * @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
+     * Nacos is in broken states.
+     */
+    @GetMapping("/liveness")
+    public ResponseEntity<String> liveness() {
+        return ResponseEntity.ok().body("OK");
+    }
+    
+    /**
+     * Ready to receive the request or not.
+     *
+     * @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not
+     * ready.
+     */
+    @GetMapping("/readiness")
+    public ResponseEntity<String> readiness(HttpServletRequest request) {
+        boolean isConfigReadiness = isConfigReadiness();
+        boolean isNamingReadiness = isNamingReadiness(request);
+        
+        if (isConfigReadiness && isNamingReadiness) {
+            return ResponseEntity.ok().body("OK");
+        }
+        
+        if (!isConfigReadiness && !isNamingReadiness) {
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Config and Naming are not in readiness");
+        }
+        
+        if (!isConfigReadiness) {
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Config is not in readiness");
+        }
+        
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Naming is not in readiness");
+    }
+    
+    private boolean isConfigReadiness() {
+        // check db
+        try {
+            configInfoPersistService.configInfoCount("");
+            return true;
+        } catch (Exception e) {
+            LOGGER.error("Config health check fail.", e);
+        }
+        return false;
+    }
+    
+    private boolean isNamingReadiness(HttpServletRequest request) {
+        try {
+            apiCommands.metrics(request);
+            return true;
+        } catch (Exception e) {
+            LOGGER.error("Naming health check fail.", e);
+        }
+        return false;
+    }
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java
new file mode 100644
index 0000000..ffe1e31
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java
@@ -0,0 +1,155 @@
+/*
+ * 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.console.controller;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.auth.annotation.Secured;
+import com.alibaba.nacos.common.model.RestResult;
+import com.alibaba.nacos.common.model.RestResultUtils;
+import com.alibaba.nacos.common.utils.StringUtils;
+import com.alibaba.nacos.config.server.service.repository.CommonPersistService;
+import com.alibaba.nacos.console.model.Namespace;
+import com.alibaba.nacos.console.model.NamespaceAllInfo;
+import com.alibaba.nacos.console.service.NamespaceOperationService;
+import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
+import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+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;
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+/**
+ * namespace service.
+ *
+ * @author Nacos
+ */
+@RestController
+@RequestMapping("/v1/console/namespaces")
+public class NamespaceController {
+    
+    @Autowired
+    private CommonPersistService commonPersistService;
+    
+    @Autowired
+    private NamespaceOperationService namespaceOperationService;
+    
+    private final Pattern namespaceIdCheckPattern = Pattern.compile("^[\\w-]+");
+    
+    private static final int NAMESPACE_ID_MAX_LENGTH = 128;
+    
+    /**
+     * Get namespace list.
+     *
+     * @return namespace list
+     */
+    @GetMapping
+    public RestResult<List<Namespace>> getNamespaces() {
+        return RestResultUtils.success(namespaceOperationService.getNamespaceList());
+    }
+    
+    /**
+     * get namespace all info by namespace id.
+     *
+     * @param namespaceId namespaceId
+     * @return namespace all info
+     */
+    @GetMapping(params = "show=all")
+    public NamespaceAllInfo getNamespace(@RequestParam("namespaceId") String namespaceId) throws NacosException {
+        return namespaceOperationService.getNamespace(namespaceId);
+    }
+    
+    /**
+     * create namespace.
+     *
+     * @param namespaceName namespace Name
+     * @param namespaceDesc namespace Desc
+     * @return whether create ok
+     */
+    @PostMapping
+    @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE)
+    public Boolean createNamespace(@RequestParam("customNamespaceId") String namespaceId,
+            @RequestParam("namespaceName") String namespaceName,
+            @RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) {
+        if (StringUtils.isBlank(namespaceId)) {
+            namespaceId = UUID.randomUUID().toString();
+        } else {
+            namespaceId = namespaceId.trim();
+            if (!namespaceIdCheckPattern.matcher(namespaceId).matches()) {
+                return false;
+            }
+            if (namespaceId.length() > NAMESPACE_ID_MAX_LENGTH) {
+                return false;
+            }
+        }
+        try {
+            return namespaceOperationService.createNamespace(namespaceId, namespaceName, namespaceDesc);
+        } catch (NacosException e) {
+            return false;
+        }
+    }
+    
+    /**
+     * check namespaceId exist.
+     *
+     * @param namespaceId namespace id
+     * @return true if exist, otherwise false
+     */
+    @GetMapping(params = "checkNamespaceIdExist=true")
+    public Boolean checkNamespaceIdExist(@RequestParam("customNamespaceId") String namespaceId) {
+        if (StringUtils.isBlank(namespaceId)) {
+            return false;
+        }
+        return (commonPersistService.tenantInfoCountByTenantId(namespaceId) > 0);
+    }
+    
+    /**
+     * edit namespace.
+     *
+     * @param namespace         namespace
+     * @param namespaceShowName namespace ShowName
+     * @param namespaceDesc     namespace Desc
+     * @return whether edit ok
+     */
+    @PutMapping
+    @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE)
+    public Boolean editNamespace(@RequestParam("namespace") String namespace,
+            @RequestParam("namespaceShowName") String namespaceShowName,
+            @RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) {
+        return namespaceOperationService.editNamespace(namespace, namespaceShowName, namespaceDesc);
+    }
+    
+    /**
+     * del namespace by id.
+     *
+     * @param namespaceId namespace Id
+     * @return whether del ok
+     */
+    @DeleteMapping
+    @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE)
+    public Boolean deleteNamespace(@RequestParam("namespaceId") String namespaceId) {
+        return namespaceOperationService.removeNamespace(namespaceId);
+    }
+    
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java
new file mode 100644
index 0000000..aa5ead4
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java
@@ -0,0 +1,55 @@
+/*
+ * 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.console.controller;
+
+import com.alibaba.nacos.common.utils.VersionUtils;
+import com.alibaba.nacos.sys.env.EnvUtil;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Server state controller.
+ *
+ * @author xingxuechao on:2019/2/27 11:17 AM
+ */
+@RestController
+@RequestMapping("/v1/console/server")
+public class ServerStateController {
+    
+    /**
+     * Get server state of current server.
+     *
+     * @return state json.
+     */
+    @GetMapping("/state")
+    public ResponseEntity<Map<String, String>> serverState() {
+        Map<String, String> serverState = new HashMap<>(4);
+        serverState.put("standalone_mode",
+                EnvUtil.getStandaloneMode() ? EnvUtil.STANDALONE_MODE_ALONE : EnvUtil.STANDALONE_MODE_CLUSTER);
+        
+        serverState.put("function_mode", EnvUtil.getFunctionMode());
+        serverState.put("version", VersionUtils.version);
+        
+        return ResponseEntity.ok().body(serverState);
+    }
+    
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java
new file mode 100644
index 0000000..c01325d
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 1999-2022 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.nacos.console.controller.v2;
+
+import com.alibaba.nacos.api.annotation.NacosApi;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.exception.api.NacosApiException;
+import com.alibaba.nacos.api.model.v2.ErrorCode;
+import com.alibaba.nacos.api.model.v2.Result;
+import com.alibaba.nacos.auth.annotation.Secured;
+import com.alibaba.nacos.common.utils.StringUtils;
+import com.alibaba.nacos.console.model.Namespace;
+import com.alibaba.nacos.console.model.NamespaceAllInfo;
+import com.alibaba.nacos.console.model.form.NamespaceForm;
+import com.alibaba.nacos.console.service.NamespaceOperationService;
+import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
+import com.alibaba.nacos.plugin.auth.constant.SignType;
+import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+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;
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+/**
+ * NamespaceControllerV2.
+ *
+ * @author dongyafei
+ * @date 2022/8/16
+ */
+@NacosApi
+@RestController
+@RequestMapping("/v2/console/namespace")
+public class NamespaceControllerV2 {
+    
+    private final NamespaceOperationService namespaceOperationService;
+    
+    public NamespaceControllerV2(NamespaceOperationService namespaceOperationService) {
+        this.namespaceOperationService = namespaceOperationService;
+    }
+    
+    private final Pattern namespaceIdCheckPattern = Pattern.compile("^[\\w-]+");
+    
+    private static final int NAMESPACE_ID_MAX_LENGTH = 128;
+    
+    /**
+     * Get namespace list.
+     *
+     * @return namespace list
+     */
+    @GetMapping("/list")
+    public Result<List<Namespace>> getNamespaceList() {
+        return Result.success(namespaceOperationService.getNamespaceList());
+    }
+    
+    /**
+     * get namespace all info by namespace id.
+     *
+     * @param namespaceId namespaceId
+     * @return namespace all info
+     */
+    @GetMapping()
+    @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX
+            + "namespaces", action = ActionTypes.READ, signType = SignType.CONSOLE)
+    public Result<NamespaceAllInfo> getNamespace(@RequestParam("namespaceId") String namespaceId)
+            throws NacosException {
+        return Result.success(namespaceOperationService.getNamespace(namespaceId));
+    }
+    
+    /**
+     * create namespace.
+     *
+     * @param namespaceForm namespaceForm.
+     * @return whether create ok
+     */
+    @PostMapping
+    @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX
+            + "namespaces", action = ActionTypes.WRITE, signType = SignType.CONSOLE)
+    public Result<Boolean> createNamespace(NamespaceForm namespaceForm) throws NacosException {
+        
+        namespaceForm.validate();
+        
+        String namespaceId = namespaceForm.getNamespaceId();
+        String namespaceName = namespaceForm.getNamespaceName();
+        String namespaceDesc = namespaceForm.getNamespaceDesc();
+        
+        if (StringUtils.isBlank(namespaceId)) {
+            namespaceId = UUID.randomUUID().toString();
+        } else {
+            namespaceId = namespaceId.trim();
+            if (!namespaceIdCheckPattern.matcher(namespaceId).matches()) {
+                throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.ILLEGAL_NAMESPACE,
+                        "namespaceId [" + namespaceId + "] mismatch the pattern");
+            }
+            if (namespaceId.length() > NAMESPACE_ID_MAX_LENGTH) {
+                throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.ILLEGAL_NAMESPACE,
+                        "too long namespaceId, over " + NAMESPACE_ID_MAX_LENGTH);
+            }
+        }
+        return Result.success(namespaceOperationService.createNamespace(namespaceId, namespaceName, namespaceDesc));
+    }
+    
+    /**
+     * edit namespace.
+     *
+     * @param namespaceForm namespace params
+     * @return whether edit ok
+     */
+    @PutMapping
+    @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX
+            + "namespaces", action = ActionTypes.WRITE, signType = SignType.CONSOLE)
+    public Result<Boolean> editNamespace(NamespaceForm namespaceForm) throws NacosException {
+        namespaceForm.validate();
+        return Result.success(namespaceOperationService
+                .editNamespace(namespaceForm.getNamespaceId(), namespaceForm.getNamespaceName(),
+                        namespaceForm.getNamespaceDesc()));
+    }
+    
+    /**
+     * delete namespace by id.
+     *
+     * @param namespaceId namespace ID
+     * @return whether delete ok
+     */
+    @DeleteMapping
+    @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX
+            + "namespaces", action = ActionTypes.WRITE, signType = SignType.CONSOLE)
+    public Result<Boolean> deleteNamespace(@RequestParam("namespaceId") String namespaceId) {
+        return Result.success(namespaceOperationService.removeNamespace(namespaceId));
+    }
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/enums/NamespaceTypeEnum.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/enums/NamespaceTypeEnum.java
new file mode 100644
index 0000000..8674ce8
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/enums/NamespaceTypeEnum.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.nacos.console.enums;
+
+/**
+ * the enum of namespace.
+ * 0 : Global configuration锛� 1 : Default private namespace 锛�2 : Custom namespace.
+ *
+ * @author chenglu
+ * @date 2021-05-25 17:01
+ */
+public enum NamespaceTypeEnum {
+    
+    /**
+     * Global configuration.
+     */
+    GLOBAL(0, "Global configuration"),
+    
+    /**
+     * Default private namespace.
+     */
+    PRIVATE(1, "Default private namespace"),
+    
+    /**
+     * Custom namespace.
+     */
+    CUSTOM(2, "Custom namespace");
+    
+    /**
+     * the namespace type.
+     */
+    private final int type;
+    
+    /**
+     * the description.
+     */
+    private final String description;
+    
+    NamespaceTypeEnum(int type, String description) {
+        this.type = type;
+        this.description = description;
+    }
+    
+    public int getType() {
+        return type;
+    }
+    
+    public String getDescription() {
+        return description;
+    }
+}
+
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java
new file mode 100644
index 0000000..b7c7fcd
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.console.exception;
+
+import com.alibaba.nacos.plugin.auth.exception.AccessException;
+import com.alibaba.nacos.common.model.RestResultUtils;
+import com.alibaba.nacos.common.utils.ExceptionUtil;
+import com.alibaba.nacos.core.utils.Commons;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Exception handler for console module.
+ *
+ * @author nkorange
+ * @since 1.2.0
+ */
+@ControllerAdvice
+public class ConsoleExceptionHandler {
+    
+    private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleExceptionHandler.class);
+    
+    @ExceptionHandler(AccessException.class)
+    private ResponseEntity<String> handleAccessException(AccessException e) {
+        LOGGER.error("got exception. {}", e.getErrMsg());
+        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getErrMsg());
+    }
+    
+    @ExceptionHandler(IllegalArgumentException.class)
+    private ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ExceptionUtil.getAllExceptionMsg(e));
+    }
+    
+    @ExceptionHandler(Exception.class)
+    private ResponseEntity<Object> handleException(HttpServletRequest request, Exception e) {
+        String uri = request.getRequestURI();
+        LOGGER.error("CONSOLE {}", uri, e);
+        if (uri.contains(Commons.NACOS_SERVER_VERSION_V2)) {
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+                    .body(RestResultUtils.failed(ExceptionUtil.getAllExceptionMsg(e)));
+        }
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ExceptionUtil.getAllExceptionMsg(e));
+    }
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/NacosApiExceptionHandler.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/NacosApiExceptionHandler.java
new file mode 100644
index 0000000..df0c1f0
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/exception/NacosApiExceptionHandler.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 1999-2022 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.nacos.console.exception;
+
+import com.alibaba.nacos.api.annotation.NacosApi;
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.exception.api.NacosApiException;
+import com.alibaba.nacos.api.model.v2.ErrorCode;
+import com.alibaba.nacos.api.model.v2.Result;
+import com.alibaba.nacos.common.utils.ExceptionUtil;
+import com.alibaba.nacos.plugin.auth.exception.AccessException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.Order;
+import org.springframework.dao.DataAccessException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.HttpMessageConversionException;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.HttpMediaTypeException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.servlet.ServletException;
+import java.io.IOException;
+
+/**
+ * Exception Handler for Nacos API.
+ * @author dongyafei
+ * @date 2022/7/22
+ */
+
+@Order(-1)
+@ControllerAdvice(annotations = {NacosApi.class})
+@ResponseBody
+public class NacosApiExceptionHandler {
+    
+    private static final Logger LOGGER = LoggerFactory.getLogger(NacosApiExceptionHandler.class);
+    
+    @ExceptionHandler(NacosApiException.class)
+    public ResponseEntity<Result<String>> handleNacosApiException(NacosApiException e) {
+        LOGGER.error("got exception. {} {}", e.getErrAbstract(), e.getErrMsg());
+        return ResponseEntity.status(e.getErrCode()).body(new Result<>(e.getDetailErrCode(), e.getErrAbstract(), e.getErrMsg()));
+    }
+    
+    @ExceptionHandler(NacosException.class)
+    public ResponseEntity<Result<String>> handleNacosException(NacosException e) {
+        LOGGER.error("got exception. {}", e.getErrMsg());
+        return ResponseEntity.status(e.getErrCode()).body(Result.failure(ErrorCode.SERVER_ERROR, e.getErrMsg()));
+    }
+    
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(HttpMessageNotReadableException.class)
+    public Result<String> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.PARAMETER_MISSING, e.getMessage());
+    }
+    
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(HttpMessageConversionException.class)
+    public Result<String> handleHttpMessageConversionException(HttpMessageConversionException e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.PARAMETER_VALIDATE_ERROR, e.getMessage());
+    }
+    
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(NumberFormatException.class)
+    public Result<String> handleNumberFormatException(NumberFormatException e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.PARAMETER_VALIDATE_ERROR, e.getMessage());
+    }
+    
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(IllegalArgumentException.class)
+    public Result<String> handleIllegalArgumentException(IllegalArgumentException e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.PARAMETER_VALIDATE_ERROR, e.getMessage());
+    }
+    
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(MissingServletRequestParameterException.class)
+    public Result<String> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.PARAMETER_MISSING, e.getMessage());
+    }
+    
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(HttpMediaTypeException.class)
+    public Result<String> handleHttpMediaTypeException(HttpMediaTypeException e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.MEDIA_TYPE_ERROR, e.getMessage());
+    }
+    
+    @ResponseStatus(HttpStatus.FORBIDDEN)
+    @ExceptionHandler(AccessException.class)
+    public Result<String> handleAccessException(AccessException e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.ACCESS_DENIED, e.getErrMsg());
+    }
+    
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(value = {DataAccessException.class, ServletException.class, IOException.class})
+    public Result<String> handleDataAccessException(Exception e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(ErrorCode.DATA_ACCESS_ERROR, e.getMessage());
+    }
+    
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(Exception.class)
+    public Result<String> handleOtherException(Exception e) {
+        LOGGER.error("got exception. {} {}", e.getMessage(), ExceptionUtil.getAllExceptionMsg(e));
+        return Result.failure(e.getMessage());
+    }
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/filter/XssFilter.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/filter/XssFilter.java
new file mode 100644
index 0000000..192a609
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/filter/XssFilter.java
@@ -0,0 +1,44 @@
+/*
+ * 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.console.filter;
+
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * XSS filter.
+ * @author onewe
+ */
+public class XssFilter extends OncePerRequestFilter {
+    
+    private static final String CONTENT_SECURITY_POLICY_HEADER = "Content-Security-Policy";
+    
+    private static final String CONTENT_SECURITY_POLICY = "script-src 'self'";
+    
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        
+        response.setHeader(CONTENT_SECURITY_POLICY_HEADER, CONTENT_SECURITY_POLICY);
+        filterChain.doFilter(request, response);
+    }
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/Namespace.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/Namespace.java
new file mode 100644
index 0000000..0a13166
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/Namespace.java
@@ -0,0 +1,115 @@
+/*
+ * 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.console.model;
+
+/**
+ * Namespace.
+ *
+ * @author diamond
+ */
+public class Namespace {
+    
+    private String namespace;
+    
+    private String namespaceShowName;
+    
+    private String namespaceDesc;
+    
+    private int quota;
+    
+    private int configCount;
+    
+    /**
+     * see {@link com.alibaba.nacos.console.enums.NamespaceTypeEnum}.
+     */
+    private int type;
+    
+    public String getNamespaceShowName() {
+        return namespaceShowName;
+    }
+    
+    public void setNamespaceShowName(String namespaceShowName) {
+        this.namespaceShowName = namespaceShowName;
+    }
+    
+    public String getNamespace() {
+        return namespace;
+    }
+    
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+    
+    public Namespace() {
+    }
+    
+    public Namespace(String namespace, String namespaceShowName) {
+        this.namespace = namespace;
+        this.namespaceShowName = namespaceShowName;
+    }
+    
+    public Namespace(String namespace, String namespaceShowName, int quota, int configCount, int type) {
+        this.namespace = namespace;
+        this.namespaceShowName = namespaceShowName;
+        this.quota = quota;
+        this.configCount = configCount;
+        this.type = type;
+    }
+    
+    public Namespace(String namespace, String namespaceShowName, String namespaceDesc, int quota, int configCount,
+            int type) {
+        this.namespace = namespace;
+        this.namespaceShowName = namespaceShowName;
+        this.quota = quota;
+        this.configCount = configCount;
+        this.type = type;
+        this.namespaceDesc = namespaceDesc;
+    }
+    
+    public String getNamespaceDesc() {
+        return namespaceDesc;
+    }
+    
+    public void setNamespaceDesc(String namespaceDesc) {
+        this.namespaceDesc = namespaceDesc;
+    }
+    
+    public int getQuota() {
+        return quota;
+    }
+    
+    public void setQuota(int quota) {
+        this.quota = quota;
+    }
+    
+    public int getConfigCount() {
+        return configCount;
+    }
+    
+    public void setConfigCount(int configCount) {
+        this.configCount = configCount;
+    }
+    
+    public int getType() {
+        return type;
+    }
+    
+    public void setType(int type) {
+        this.type = type;
+    }
+    
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/NamespaceAllInfo.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/NamespaceAllInfo.java
new file mode 100644
index 0000000..92d9c8f
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/NamespaceAllInfo.java
@@ -0,0 +1,31 @@
+/*
+ * 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.console.model;
+
+/**
+ * all namespace info.
+ *
+ * @author Nacos
+ */
+public class NamespaceAllInfo extends Namespace {
+    
+    public NamespaceAllInfo(String namespace, String namespaceShowName, int quota, int configCount, int type,
+            String namespaceDesc) {
+        super(namespace, namespaceShowName, namespaceDesc, quota, configCount, type);
+    }
+    
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/form/NamespaceForm.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/form/NamespaceForm.java
new file mode 100644
index 0000000..851429a
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/model/form/NamespaceForm.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1999-2022 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.nacos.console.model.form;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.exception.api.NacosApiException;
+import com.alibaba.nacos.api.model.v2.ErrorCode;
+import org.springframework.http.HttpStatus;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * NamespaceForm.
+ * @author dongyafei
+ * @date 2022/8/16
+ */
+public class NamespaceForm implements Serializable {
+    
+    private static final long serialVersionUID = -1078976569495343487L;
+    
+    private String namespaceId;
+    
+    private String namespaceName;
+    
+    private String namespaceDesc;
+    
+    public NamespaceForm() {
+    }
+    
+    public NamespaceForm(String namespaceId, String namespaceName, String namespaceDesc) {
+        this.namespaceId = namespaceId;
+        this.namespaceName = namespaceName;
+        this.namespaceDesc = namespaceDesc;
+    }
+    
+    public String getNamespaceId() {
+        return namespaceId;
+    }
+    
+    public void setNamespaceId(String namespaceId) {
+        this.namespaceId = namespaceId;
+    }
+    
+    public String getNamespaceName() {
+        return namespaceName;
+    }
+    
+    public void setNamespaceName(String namespaceName) {
+        this.namespaceName = namespaceName;
+    }
+    
+    public String getNamespaceDesc() {
+        return namespaceDesc;
+    }
+    
+    public void setNamespaceDesc(String namespaceDesc) {
+        this.namespaceDesc = namespaceDesc;
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        NamespaceForm that = (NamespaceForm) o;
+        return Objects.equals(namespaceId, that.namespaceId) && Objects.equals(namespaceName, that.namespaceName)
+                && Objects.equals(namespaceDesc, that.namespaceDesc);
+    }
+    
+    @Override
+    public int hashCode() {
+        return Objects.hash(namespaceId, namespaceName, namespaceDesc);
+    }
+    
+    @Override
+    public String toString() {
+        return "NamespaceVo{" + "namespaceId='" + namespaceId + '\'' + ", namespaceName='" + namespaceName + '\''
+                + ", namespaceDesc='" + namespaceDesc + '\'' + '}';
+    }
+    
+    /**
+     * check required param.
+     * @throws NacosException NacosException
+     */
+    public void validate() throws NacosException {
+        if (null == namespaceId) {
+            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING, "required parameter 'namespaceId' is missing");
+        }
+        if (null == namespaceName) {
+            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING, "required parameter 'namespaceName' is missing");
+        }
+    }
+}
diff --git a/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java
new file mode 100644
index 0000000..199261e
--- /dev/null
+++ b/ruoyi-visual/ruoyi-nacos/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 1999-2022 Alibaba Group Holding Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.nacos.console.service;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import com.alibaba.nacos.api.exception.api.NacosApiException;
+import com.alibaba.nacos.api.model.v2.ErrorCode;
+import com.alibaba.nacos.common.utils.NamespaceUtil;
+import com.alibaba.nacos.common.utils.StringUtils;
+import com.alibaba.nacos.config.server.model.TenantInfo;
+import com.alibaba.nacos.config.server.service.repository.CommonPersistService;
+import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
+import com.alibaba.nacos.console.enums.NamespaceTypeEnum;
+import com.alibaba.nacos.console.model.Namespace;
+import com.alibaba.nacos.console.model.NamespaceAllInfo;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NamespaceOperationService.
+ *
+ * @author dongyafei
+ * @date 2022/8/16
+ */
+
+@Service
+public class NamespaceOperationService {
+    
+    private final ConfigInfoPersistService configInfoPersistService;
+    
+    private final CommonPersistService commonPersistService;
+    
+    private static final String DEFAULT_NAMESPACE = "public";
+    
+    private static final String DEFAULT_NAMESPACE_SHOW_NAME = "Public";
+    
+    private static final String DEFAULT_NAMESPACE_DESCRIPTION = "Public Namespace";
+    
+    private static final int DEFAULT_QUOTA = 200;
+    
+    private static final String DEFAULT_CREATE_SOURCE = "nacos";
+    
+    private static final String DEFAULT_TENANT = "";
+    
+    private static final String DEFAULT_KP = "1";
+    
+    public NamespaceOperationService(ConfigInfoPersistService configInfoPersistService,
+            CommonPersistService commonPersistService) {
+        this.configInfoPersistService = configInfoPersistService;
+        this.commonPersistService = commonPersistService;
+    }
+    
+    public List<Namespace> getNamespaceList() {
+        // TODO 鑾峰彇鐢╧p
+        List<TenantInfo> tenantInfos = commonPersistService.findTenantByKp(DEFAULT_KP);
+        
+        Namespace namespace0 = new Namespace(NamespaceUtil.getNamespaceDefaultId(), DEFAULT_NAMESPACE, DEFAULT_QUOTA,
+                configInfoPersistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType());
+        List<Namespace> namespaceList = new ArrayList<>();
+        namespaceList.add(namespace0);
+        
+        for (TenantInfo tenantInfo : tenantInfos) {
+            int configCount = configInfoPersistService.configInfoCount(tenantInfo.getTenantId());
+            Namespace namespaceTmp = new Namespace(tenantInfo.getTenantId(), tenantInfo.getTenantName(),
+                    tenantInfo.getTenantDesc(), DEFAULT_QUOTA, configCount, NamespaceTypeEnum.CUSTOM.getType());
+            namespaceList.add(namespaceTmp);
+        }
+        return namespaceList;
+    }
+    
+    /**
+     * query namespace by namespace id.
+     *
+     * @param namespaceId namespace Id.
+     * @return NamespaceAllInfo.
+     */
+    public NamespaceAllInfo getNamespace(String namespaceId) throws NacosException {
+        // TODO 鑾峰彇鐢╧p
+        if (StringUtils.isBlank(namespaceId) || namespaceId.equals(NamespaceUtil.getNamespaceDefaultId())) {
+            return new NamespaceAllInfo(namespaceId, DEFAULT_NAMESPACE_SHOW_NAME, DEFAULT_QUOTA,
+                    configInfoPersistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType(),
+                    DEFAULT_NAMESPACE_DESCRIPTION);
+        } else {
+            TenantInfo tenantInfo = commonPersistService.findTenantByKp(DEFAULT_KP, namespaceId);
+            if (null == tenantInfo) {
+                throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.NAMESPACE_NOT_EXIST,
+                        "namespaceId [ " + namespaceId + " ] not exist");
+            }
+            int configCount = configInfoPersistService.configInfoCount(namespaceId);
+            return new NamespaceAllInfo(namespaceId, tenantInfo.getTenantName(), DEFAULT_QUOTA, configCount,
+                    NamespaceTypeEnum.CUSTOM.getType(), tenantInfo.getTenantDesc());
+        }
+    }
+    
+    /**
+     * create namespace.
+     *
+     * @param namespaceId   namespace ID
+     * @param namespaceName namespace Name
+     * @param namespaceDesc namespace Desc
+     * @return whether create ok
+     */
+    public Boolean createNamespace(String namespaceId, String namespaceName, String namespaceDesc)
+            throws NacosException {
+        // TODO 鑾峰彇鐢╧p
+        if (commonPersistService.tenantInfoCountByTenantId(namespaceId) > 0) {
+            throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.NAMESPACE_ALREADY_EXIST,
+                    "namespaceId [" + namespaceId + "] already exist");
+        }
+    
+        commonPersistService
+                .insertTenantInfoAtomic(DEFAULT_KP, namespaceId, namespaceName, namespaceDesc, DEFAULT_CREATE_SOURCE,
+                        System.currentTimeMillis());
+        return true;
+    }
+    
+    /**
+     * edit namespace.
+     */
+    public Boolean editNamespace(String namespaceId, String namespaceName, String namespaceDesc) {
+        // TODO 鑾峰彇鐢╧p
+        commonPersistService.updateTenantNameAtomic(DEFAULT_KP, namespaceId, namespaceName, namespaceDesc);
+        return true;
+    }
+    
+    /**
+     * remove namespace.
+     */
+    public Boolean removeNamespace(String namespaceId) {
+        commonPersistService.removeTenantInfoAtomic(DEFAULT_KP, namespaceId);
+        return true;
+    }
+}

--
Gitblit v1.9.1