diff --git a/BUILDING b/BUILDING index e7e968b8b..214f330ff 100644 --- a/BUILDING +++ b/BUILDING @@ -35,4 +35,4 @@ Build Instructions for NACOS Execute the following command in order to build the tar.gz packages and install JAR into local repository: #build nacos - $ mvn -Prelease-nacos -DskipTests clean install -U \ No newline at end of file + $ mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U diff --git a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java index 10c03dbda..ae33529c7 100644 --- a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java +++ b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java @@ -76,6 +76,8 @@ public class Constants { public static final String TOKEN_TTL = "tokenTtl"; + public static final String GLOBAL_ADMIN = "globalAdmin"; + public static final String TOKEN_REFRESH_WINDOW = "tokenRefreshWindow"; /** diff --git a/config/src/main/resources/META-INF/nacos-db.sql b/config/src/main/resources/META-INF/nacos-db.sql index 73bef7b76..14a2e2b74 100644 --- a/config/src/main/resources/META-INF/nacos-db.sql +++ b/config/src/main/resources/META-INF/nacos-db.sql @@ -189,6 +189,13 @@ CREATE TABLE roles ( role varchar(50) NOT NULL ); +CREATE TABLE permissions ( + role varchar(50) NOT NULL, + resource varchar(512) NOT NULL, + action varchar(8) NOT NULL, + constraint uk_role_permission UNIQUE (role,resource,action) +); + INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE); -INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN'); +INSERT INTO roles (username, role) VALUES ('nacos', 'GLOBAL_ADMIN'); diff --git a/config/src/main/resources/META-INF/schema.sql b/config/src/main/resources/META-INF/schema.sql index 5489d69fa..43249fd5c 100644 --- a/config/src/main/resources/META-INF/schema.sql +++ b/config/src/main/resources/META-INF/schema.sql @@ -184,6 +184,13 @@ CREATE TABLE roles ( role varchar(50) NOT NULL ); +CREATE TABLE permissions ( + role varchar(50) NOT NULL, + resource varchar(512) NOT NULL, + action varchar(8) NOT NULL, + constraint uk_role_permission UNIQUE (role,resource,action) +); + INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE); -INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN'); +INSERT INTO roles (username, role) VALUES ('nacos', 'GLOBAL_ADMIN'); diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/UserController.java b/console/src/main/java/com/alibaba/nacos/console/controller/UserController.java index f38bc7cd5..523bb0f43 100644 --- a/console/src/main/java/com/alibaba/nacos/console/controller/UserController.java +++ b/console/src/main/java/com/alibaba/nacos/console/controller/UserController.java @@ -76,7 +76,7 @@ public class UserController { @PostMapping public Object createUser(@RequestParam String username, @RequestParam String password) { - User user = userDetailsService.getUser(username); + User user = userDetailsService.getUserFromDatabase(username); if (user != null) { throw new IllegalArgumentException("user '" + username + "' already exist!"); } @@ -112,7 +112,7 @@ public class UserController { @Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE) public Object updateUser(@RequestParam String username, @RequestParam String newPassword) { - User user = userDetailsService.getUser(username); + User user = userDetailsService.getUserFromDatabase(username); if (user == null) { throw new IllegalArgumentException("user " + username + " not exist!"); } @@ -162,6 +162,7 @@ public class UserController { JSONObject result = new JSONObject(); result.put(Constants.ACCESS_TOKEN, user.getToken()); result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds()); + result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin()); return result; } @@ -196,8 +197,8 @@ public class UserController { RestResult rr = new RestResult(); Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String username = ((UserDetails) principal).getUsername(); - UserDetails userDetails = userDetailsService.loadUserByUsername(username); - String password = userDetails.getPassword(); + User user = userDetailsService.getUserFromDatabase(username); + String password = user.getPassword(); // TODO: throw out more fine grained exceptions try { diff --git a/console/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java b/console/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java index 402d7ac3c..9d9d285a3 100644 --- a/console/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java +++ b/console/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java @@ -16,6 +16,8 @@ package com.alibaba.nacos.console.exception; import com.alibaba.nacos.core.auth.AccessException; +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; @@ -30,9 +32,10 @@ import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice public class ConsoleExceptionHandler { + private static final Logger logger = LoggerFactory.getLogger(ConsoleExceptionHandler.class); + @ExceptionHandler(AccessException.class) private ResponseEntity handleAccessException(AccessException e) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getErrMsg()); } @@ -40,4 +43,10 @@ public class ConsoleExceptionHandler { private ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.toString()); } + + @ExceptionHandler(Exception.class) + private ResponseEntity handleException(Exception e) { + logger.error("CONSOLE", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.toString()); + } } diff --git a/console/src/main/java/com/alibaba/nacos/console/security/nacos/NacosAuthManager.java b/console/src/main/java/com/alibaba/nacos/console/security/nacos/NacosAuthManager.java index 77a5d52b6..3386a5efb 100644 --- a/console/src/main/java/com/alibaba/nacos/console/security/nacos/NacosAuthManager.java +++ b/console/src/main/java/com/alibaba/nacos/console/security/nacos/NacosAuthManager.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.console.security.nacos; import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.config.server.auth.RoleInfo; 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; @@ -34,6 +35,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; +import java.util.List; /** * Builtin access control entry of Nacos @@ -74,10 +76,17 @@ public class NacosAuthManager implements AuthManager { Authentication authentication = tokenManager.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); - String userId = authentication.getName(); + String username = authentication.getName(); NacosUser user = new NacosUser(); - user.setUserName(userId); + user.setUserName(username); user.setToken(token); + List roleInfoList = roleService.getRoles(username); + for (RoleInfo roleInfo : roleInfoList) { + if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) { + user.setGlobalAdmin(true); + break; + } + } return user; } diff --git a/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java b/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java index 2d71bff95..212500b4b 100644 --- a/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java +++ b/console/src/main/java/com/alibaba/nacos/console/security/nacos/roles/NacosRoleServiceImpl.java @@ -23,6 +23,7 @@ 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; @@ -44,7 +45,10 @@ import java.util.regex.Pattern; @Service public class NacosRoleServiceImpl { - private static final String GLOBAL_ADMIN_ROLE = "GLOBAL_ADMIN"; + public static final String GLOBAL_ADMIN_ROLE = "GLOBAL_ADMIN"; + + @Autowired + private AuthConfigs authConfigs; @Autowired private RolePersistService rolePersistService; @@ -95,13 +99,13 @@ public class NacosRoleServiceImpl { * Note if the user has many roles, this method returns true if any one role of the user has the * desired permission. * - * @param username user info + * @param username user info * @param permission permission to auth * @return true if granted, false otherwise */ public boolean hasPermission(String username, Permission permission) { - List roleInfoList = roleInfoMap.get(username); + List roleInfoList = getRoles(username); if (Collections.isEmpty(roleInfoList)) { return false; } @@ -120,7 +124,7 @@ public class NacosRoleServiceImpl { // For other roles, use a pattern match to decide if pass or not. for (RoleInfo roleInfo : roleInfoList) { - List permissionInfoList = permissionInfoMap.get(roleInfo.getRole()); + List permissionInfoList = getPermissions(roleInfo.getRole()); if (Collections.isEmpty(permissionInfoList)) { continue; } @@ -136,11 +140,36 @@ public class NacosRoleServiceImpl { return false; } + public List getRoles(String username) { + List roleInfoList = roleInfoMap.get(username); + if (!authConfigs.isCachingEnabled()) { + Page roleInfoPage = getRolesFromDatabase(username, 1, Integer.MAX_VALUE); + if (roleInfoPage != null) { + roleInfoList = roleInfoPage.getPageItems(); + } + } + return roleInfoList; + } + public Page getRolesFromDatabase(String userName, int pageNo, int pageSize) { Page roles = rolePersistService.getRolesByUserName(userName, pageNo, pageSize); + if (roles == null) { + return new Page<>(); + } return roles; } + public List getPermissions(String role) { + List permissionInfoList = permissionInfoMap.get(role); + if (!authConfigs.isCachingEnabled()) { + Page permissionInfoPage = getPermissionsFromDatabase(role, 1, Integer.MAX_VALUE); + if (permissionInfoPage != null) { + permissionInfoList = permissionInfoPage.getPageItems(); + } + } + return permissionInfoList; + } + public Page getPermissionsByRoleFromDatabase(String role, int pageNo, int pageSize) { return permissionPersistService.getPermissions(role, pageNo, pageSize); } @@ -157,11 +186,15 @@ public class NacosRoleServiceImpl { } public void deleteRole(String role) { + rolePersistService.deleteRole(role); } public Page getPermissionsFromDatabase(String role, int pageNo, int pageSize) { Page pageInfo = permissionPersistService.getPermissions(role, pageNo, pageSize); + if (pageInfo == null) { + return new Page<>(); + } return pageInfo; } diff --git a/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUser.java b/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUser.java index 3e05687be..f2f519c58 100644 --- a/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUser.java +++ b/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUser.java @@ -27,6 +27,8 @@ public class NacosUser extends User { private String token; + private boolean globalAdmin = false; + public String getToken() { return token; } @@ -35,6 +37,14 @@ public class NacosUser extends User { this.token = token; } + public boolean isGlobalAdmin() { + return globalAdmin; + } + + public void setGlobalAdmin(boolean globalAdmin) { + this.globalAdmin = globalAdmin; + } + @Override public String toString() { return JSON.toJSONString(this); diff --git a/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUserDetailsServiceImpl.java b/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUserDetailsServiceImpl.java index 864f30a55..7c9b66ceb 100644 --- a/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUserDetailsServiceImpl.java +++ b/console/src/main/java/com/alibaba/nacos/console/security/nacos/users/NacosUserDetailsServiceImpl.java @@ -19,6 +19,7 @@ package com.alibaba.nacos.console.security.nacos.users; 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; @@ -44,6 +45,9 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService { @Autowired private UserPersistService userPersistService; + @Autowired + private AuthConfigs authConfigs; + @Scheduled(initialDelay = 5000, fixedDelay = 15000) private void reload() { try { @@ -66,6 +70,10 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userMap.get(username); + if (!authConfigs.isCachingEnabled()) { + user = userPersistService.findUserByUsername(username); + } + if (user == null) { throw new UsernameNotFoundException(username); } @@ -81,7 +89,15 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService { } public User getUser(String username) { - return userMap.get(username); + User user = userMap.get(username); + if (!authConfigs.isCachingEnabled()) { + user = getUserFromDatabase(username); + } + return user; + } + + public User getUserFromDatabase(String username) { + return userPersistService.findUserByUsername(username); } public void createUser(String username, String password) { diff --git a/core/src/main/java/com/alibaba/nacos/core/auth/AuthConfigs.java b/core/src/main/java/com/alibaba/nacos/core/auth/AuthConfigs.java index 198bb3c40..283aeb61c 100644 --- a/core/src/main/java/com/alibaba/nacos/core/auth/AuthConfigs.java +++ b/core/src/main/java/com/alibaba/nacos/core/auth/AuthConfigs.java @@ -74,6 +74,11 @@ public class AuthConfigs { .getProperty("nacos.core.auth.enabled", "false")); } + public boolean isCachingEnabled() { + return BooleanUtils.toBoolean(reloadableConfigs.getProperties() + .getProperty("nacos.core.auth.caching.enabled", "true")); + } + @Bean public FilterRegistrationBean authFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean<>(); diff --git a/core/src/main/java/com/alibaba/nacos/core/env/ReloadableConfigs.java b/core/src/main/java/com/alibaba/nacos/core/env/ReloadableConfigs.java index b24fa673b..5c98067e2 100644 --- a/core/src/main/java/com/alibaba/nacos/core/env/ReloadableConfigs.java +++ b/core/src/main/java/com/alibaba/nacos/core/env/ReloadableConfigs.java @@ -35,13 +35,12 @@ import java.util.Properties; * @author nkorange * @since 1.2.0 */ -@ConditionalOnProperty(name = "spring.config.location", matchIfMissing = false) @Component public class ReloadableConfigs { private Properties properties; - @Value("${spring.config.location}") + @Value("${spring.config.location:}") private String path; private static final String FILE_PREFIX = "file:"; diff --git a/distribution/conf/application.properties b/distribution/conf/application.properties index 51ec9481a..4d9c5cf1d 100644 --- a/distribution/conf/application.properties +++ b/distribution/conf/application.properties @@ -104,6 +104,9 @@ nacos.core.auth.default.token.expire.seconds=18000 ### The default token: nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789 +### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay. +nacos.core.auth.caching.enabled=true + #*************** Istio Related Configurations ***************# ### If turn on the MCP server: diff --git a/naming/src/main/java/com/alibaba/nacos/naming/misc/HttpClient.java b/naming/src/main/java/com/alibaba/nacos/naming/misc/HttpClient.java index 82dc093c2..de3f2c2a1 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/misc/HttpClient.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/misc/HttpClient.java @@ -419,10 +419,7 @@ public class HttpClient { inputStream = new GZIPInputStream(inputStream); } - HttpResult result = new HttpResult(respCode, IoUtils.toString(inputStream, getCharset(conn)), respHeaders); - inputStream.close(); - - return result; + return new HttpResult(respCode, IoUtils.toString(inputStream, getCharset(conn)), respHeaders); } private static String getCharset(HttpURLConnection conn) { diff --git a/pom.xml b/pom.xml index b19551405..1801d6673 100644 --- a/pom.xml +++ b/pom.xml @@ -525,6 +525,11 @@ nacos-example ${project.version} + + ${project.groupId} + nacos-address + ${project.version} + ${project.groupId} @@ -539,12 +544,12 @@ 1.2.58 - - - javax.ws.rs - javax.ws.rs - 2.1 - + + + + + + javax.servlet diff --git a/test/pom.xml b/test/pom.xml index 7dda150ff..865693c33 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -80,6 +80,11 @@ nacos-console + + ${project.groupId} + nacos-address + + junit junit diff --git a/test/src/test/java/com/alibaba/nacos/test/core/auth/Permission_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/core/auth/Permission_ITCase.java index afde9a888..25a18558a 100644 --- a/test/src/test/java/com/alibaba/nacos/test/core/auth/Permission_ITCase.java +++ b/test/src/test/java/com/alibaba/nacos/test/core/auth/Permission_ITCase.java @@ -1,4 +1,313 @@ +/* + * 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.test.core.auth; -public class Permission_ITCase { + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.alibaba.nacos.Nacos; +import com.alibaba.nacos.config.server.model.Page; +import com.alibaba.nacos.core.auth.Permission; +import com.alibaba.nacos.test.base.HttpClient4Test; +import com.alibaba.nacos.test.base.Params; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.net.URL; +import java.util.concurrent.TimeUnit; + +/** + * @author nkorange + * @since 1.2.0 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7001"}, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class Permission_ITCase extends HttpClient4Test { + + @LocalServerPort + private int port; + + private String accessToken; + + @Before + public void init() throws Exception { + TimeUnit.SECONDS.sleep(5L); + String url = String.format("http://localhost:%d/", port); + this.base = new URL(url); + } + + @After + public void destroy() { + + // Delete permission: + ResponseEntity response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("resource", "public:*:*") + .appendParam("action", "rw") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("resource", "test1:*:*") + .appendParam("action", "r") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role1") + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete a user: + response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", "username3") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + } + + @Test + public void login() { + + ResponseEntity response = request("/nacos/v1/auth/users/login", + Params.newParams() + .appendParam("username", "nacos") + .appendParam("password", "nacos") + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + JSONObject json = JSON.parseObject(response.getBody()); + Assert.assertTrue(json.containsKey("accessToken")); + accessToken = json.getString("accessToken"); + } + + @Test + public void createDeleteQueryPermission() { + + login(); + + // Create a user: + ResponseEntity response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", "username3") + .appendParam("password", "password1") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Create role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role1") + .appendParam("username", "username3") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Create permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("resource", "public:*:*") + .appendParam("action", "rw") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Create another permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("resource", "test1:*:*") + .appendParam("action", "r") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Query permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("pageNo", "1") + .appendParam("pageSize", "10") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.GET); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + Page permissionPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); + + Assert.assertNotNull(permissionPage); + Assert.assertNotNull(permissionPage.getPageItems()); + + boolean found1=false,found2=false; + for (Permission permission : permissionPage.getPageItems()) { + if (permission.getResource().equals("public:*:*") && permission.getAction().equals("rw")) { + found1 = true; + } + if (permission.getResource().equals("test1:*:*") && permission.getAction().equals("r")) { + found2 = true; + } + if (found1 && found2) { + break; + } + } + Assert.assertTrue(found1); + Assert.assertTrue(found2); + + // Delete permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("resource", "public:*:*") + .appendParam("action", "rw") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Query permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("pageNo", "1") + .appendParam("pageSize", "10") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.GET); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + permissionPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); + + Assert.assertNotNull(permissionPage); + Assert.assertNotNull(permissionPage.getPageItems()); + + found1=false; + found2=false; + + for (Permission permission : permissionPage.getPageItems()) { + if (permission.getResource().equals("public:*:*") && permission.getAction().equals("rw")) { + found1 = true; + } + if (permission.getResource().equals("test1:*:*") && permission.getAction().equals("r")) { + found2 = true; + } + } + Assert.assertFalse(found1); + Assert.assertTrue(found2); + + // Delete permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("resource", "test1:*:*") + .appendParam("action", "r") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Query permission: + response = request("/nacos/v1/auth/permissions", + Params.newParams() + .appendParam("role", "role1") + .appendParam("pageNo", "1") + .appendParam("pageSize", "10") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.GET); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + permissionPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); + + Assert.assertNotNull(permissionPage); + Assert.assertNotNull(permissionPage.getPageItems()); + + found1=false; + found2=false; + + for (Permission permission : permissionPage.getPageItems()) { + if (permission.getResource().equals("public:*:*") && permission.getAction().equals("rw")) { + found1 = true; + } + if (permission.getResource().equals("test1:*:*") && permission.getAction().equals("r")) { + found2 = true; + } + } + Assert.assertFalse(found1); + Assert.assertFalse(found2); + } } diff --git a/test/src/test/java/com/alibaba/nacos/test/core/auth/Role_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/core/auth/Role_ITCase.java index 61b6a7e92..625364452 100644 --- a/test/src/test/java/com/alibaba/nacos/test/core/auth/Role_ITCase.java +++ b/test/src/test/java/com/alibaba/nacos/test/core/auth/Role_ITCase.java @@ -1,4 +1,306 @@ +/* + * 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.test.core.auth; -public class Role_ITCase { + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.alibaba.nacos.Nacos; +import com.alibaba.nacos.config.server.auth.RoleInfo; +import com.alibaba.nacos.config.server.model.Page; +import com.alibaba.nacos.test.base.HttpClient4Test; +import com.alibaba.nacos.test.base.Params; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.net.URL; +import java.util.concurrent.TimeUnit; + +/** + * @author nkorange + * @since 1.2.0 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7001"}, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class Role_ITCase extends HttpClient4Test { + + @LocalServerPort + private int port; + + private String accessToken; + + @Before + public void init() throws Exception { + TimeUnit.SECONDS.sleep(5L); + String url = String.format("http://localhost:%d/", port); + this.base = new URL(url); + } + + @After + public void destroy() { + + // Delete role: + ResponseEntity response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role1") + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role2") + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Delete a user: + response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + } + + @Test + public void login() { + + ResponseEntity response = request("/nacos/v1/auth/users/login", + Params.newParams() + .appendParam("username", "nacos") + .appendParam("password", "nacos") + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + JSONObject json = JSON.parseObject(response.getBody()); + Assert.assertTrue(json.containsKey("accessToken")); + accessToken = json.getString("accessToken"); + } + + @Test + public void createDeleteQueryRole() { + + login(); + + // Create a user: + ResponseEntity response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", "username2") + .appendParam("password", "password1") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Create a role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role1") + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Query role of user: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("username", "username2") + .appendParam("pageNo", "1") + .appendParam("pageSize", "10") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.GET); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + Page roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); + + Assert.assertNotNull(roleInfoPage); + Assert.assertNotNull(roleInfoPage.getPageItems()); + boolean found = false; + for (RoleInfo roleInfo : roleInfoPage.getPageItems()) { + if (roleInfo.getRole().equals("role1")) { + found = true; + break; + } + } + Assert.assertTrue(found); + + // Add second role to user: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role2") + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.POST); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Query roles of user: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("username", "username2") + .appendParam("pageNo", "1") + .appendParam("pageSize", "10") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.GET); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); + + Assert.assertNotNull(roleInfoPage); + Assert.assertNotNull(roleInfoPage.getPageItems()); + found = false; + boolean found2 = false; + for (RoleInfo roleInfo : roleInfoPage.getPageItems()) { + if (roleInfo.getRole().equals("role1")) { + found = true; + } + if (roleInfo.getRole().equals("role2")) { + found2 = true; + } + if (found && found2) { + break; + } + } + Assert.assertTrue(found); + Assert.assertTrue(found2); + + // Delete role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role2") + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Query roles of user: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("username", "username2") + .appendParam("pageNo", "1") + .appendParam("pageSize", "10") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.GET); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); + + Assert.assertNotNull(roleInfoPage); + Assert.assertNotNull(roleInfoPage.getPageItems()); + found = false; + found2 = false; + for (RoleInfo roleInfo : roleInfoPage.getPageItems()) { + if (roleInfo.getRole().equals("role1")) { + found = true; + } + if (roleInfo.getRole().equals("role2")) { + found2 = true; + } + } + Assert.assertFalse(found2); + Assert.assertTrue(found); + + // Delete role: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("role", "role1") + .appendParam("username", "username2") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + // Query roles of user: + response = request("/nacos/v1/auth/roles", + Params.newParams() + .appendParam("username", "username2") + .appendParam("pageNo", "1") + .appendParam("pageSize", "10") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.GET); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); + + roleInfoPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); + + Assert.assertNotNull(roleInfoPage); + Assert.assertNotNull(roleInfoPage.getPageItems()); + found = false; + found2 = false; + for (RoleInfo roleInfo : roleInfoPage.getPageItems()) { + if (roleInfo.getRole().equals("role1")) { + found = true; + } + if (roleInfo.getRole().equals("role2")) { + found2 = true; + } + } + Assert.assertFalse(found2); + Assert.assertFalse(found); + } } diff --git a/test/src/test/java/com/alibaba/nacos/test/core/auth/User_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/core/auth/User_ITCase.java index 4b5ba37a1..f0188e85d 100644 --- a/test/src/test/java/com/alibaba/nacos/test/core/auth/User_ITCase.java +++ b/test/src/test/java/com/alibaba/nacos/test/core/auth/User_ITCase.java @@ -1,14 +1,30 @@ +/* + * 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.test.core.auth; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; +import com.alibaba.nacos.Nacos; import com.alibaba.nacos.config.server.model.Page; import com.alibaba.nacos.config.server.model.User; import com.alibaba.nacos.console.utils.PasswordEncoderUtil; -import com.alibaba.nacos.naming.NamingApp; import com.alibaba.nacos.test.base.HttpClient4Test; import com.alibaba.nacos.test.base.Params; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -20,18 +36,17 @@ import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; import java.net.URL; +import java.util.concurrent.TimeUnit; /** * @author nkorange * @since 1.2.0 */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = NamingApp.class, properties = {"server.servlet.context-path=/nacos"}, +@SpringBootTest(classes = Nacos.class, properties = {"server.servlet.context-path=/nacos", "server.port=7001"}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class User_ITCase extends HttpClient4Test { - protected URL base; - @LocalServerPort private int port; @@ -39,18 +54,34 @@ public class User_ITCase extends HttpClient4Test { @Before public void init() throws Exception { + TimeUnit.SECONDS.sleep(5L); String url = String.format("http://localhost:%d/", port); this.base = new URL(url); - login(); + } + + @After + public void destroy() { + + // Delete a user: + ResponseEntity response = request("/nacos/v1/auth/users", + Params.newParams() + .appendParam("username", "username1") + .appendParam("accessToken", accessToken) + .done(), + String.class, + HttpMethod.DELETE); + + Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); } @Test public void login() { - ResponseEntity response = request("/nacos/v1/ns/auth/users/login", + + ResponseEntity response = request("/nacos/v1/auth/users/login", Params.newParams() - .appendParam("username", "username1") - .appendParam("password", "password1") + .appendParam("username", "nacos") + .appendParam("password", "nacos") .done(), String.class, HttpMethod.POST); @@ -64,8 +95,10 @@ public class User_ITCase extends HttpClient4Test { @Test public void createUpdateDeleteUser() { + login(); + // Create a user: - ResponseEntity response = request("/nacos/v1/ns/auth/users", + ResponseEntity response = request("/nacos/v1/auth/users", Params.newParams() .appendParam("username", "username1") .appendParam("password", "password1") @@ -77,7 +110,7 @@ public class User_ITCase extends HttpClient4Test { Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); // Query a user: - response = request("/nacos/v1/ns/auth/users", + response = request("/nacos/v1/auth/users", Params.newParams() .appendParam("pageNo", "1") .appendParam("pageSize", String.valueOf(Integer.MAX_VALUE)) @@ -87,7 +120,8 @@ public class User_ITCase extends HttpClient4Test { Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); - Page userPage = JSON.parseObject(response.getBody(), new TypeReference>(){}); + Page userPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); Assert.assertNotNull(userPage); Assert.assertNotNull(userPage.getPageItems()); @@ -96,7 +130,7 @@ public class User_ITCase extends HttpClient4Test { boolean found = false; for (User user : userPage.getPageItems()) { if ("username1".equals(user.getUsername()) && - PasswordEncoderUtil.encode("password1").equals(user.getPassword())) { + PasswordEncoderUtil.matches("password1", user.getPassword())) { found = true; break; } @@ -104,7 +138,7 @@ public class User_ITCase extends HttpClient4Test { Assert.assertTrue(found); // Update a user: - response = request("/nacos/v1/ns/auth/users", + response = request("/nacos/v1/auth/users", Params.newParams() .appendParam("username", "username1") .appendParam("newPassword", "password2") @@ -116,7 +150,7 @@ public class User_ITCase extends HttpClient4Test { Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); // Query a user: - response = request("/nacos/v1/ns/auth/users", + response = request("/nacos/v1/auth/users", Params.newParams() .appendParam("pageNo", "1") .appendParam("pageSize", String.valueOf(Integer.MAX_VALUE)) @@ -124,7 +158,8 @@ public class User_ITCase extends HttpClient4Test { .done(), String.class); - userPage = JSON.parseObject(response.getBody(), new TypeReference>(){}); + userPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); Assert.assertNotNull(userPage); Assert.assertNotNull(userPage.getPageItems()); @@ -133,7 +168,7 @@ public class User_ITCase extends HttpClient4Test { found = false; for (User user : userPage.getPageItems()) { if ("username1".equals(user.getUsername()) && - PasswordEncoderUtil.encode("password2").equals(user.getPassword())) { + PasswordEncoderUtil.matches("password2", user.getPassword())) { found = true; break; } @@ -141,7 +176,7 @@ public class User_ITCase extends HttpClient4Test { Assert.assertTrue(found); // Delete a user: - response = request("/nacos/v1/ns/auth/users", + response = request("/nacos/v1/auth/users", Params.newParams() .appendParam("username", "username1") .appendParam("accessToken", accessToken) @@ -152,7 +187,7 @@ public class User_ITCase extends HttpClient4Test { Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); // Query a user: - response = request("/nacos/v1/ns/auth/users", + response = request("/nacos/v1/auth/users", Params.newParams() .appendParam("pageNo", "1") .appendParam("pageSize", String.valueOf(Integer.MAX_VALUE)) @@ -162,7 +197,8 @@ public class User_ITCase extends HttpClient4Test { Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); - userPage = JSON.parseObject(response.getBody(), new TypeReference>(){}); + userPage = JSON.parseObject(response.getBody(), new TypeReference>() { + }); Assert.assertNotNull(userPage); Assert.assertNotNull(userPage.getPageItems()); @@ -177,5 +213,4 @@ public class User_ITCase extends HttpClient4Test { } Assert.assertFalse(found); } - } diff --git a/test/src/test/java/com/alibaba/nacos/test/naming/NamingBase.java b/test/src/test/java/com/alibaba/nacos/test/naming/NamingBase.java index 6c495ddd8..ca69fd526 100644 --- a/test/src/test/java/com/alibaba/nacos/test/naming/NamingBase.java +++ b/test/src/test/java/com/alibaba/nacos/test/naming/NamingBase.java @@ -22,16 +22,7 @@ import com.alibaba.nacos.test.base.HttpClient4Test; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; import org.junit.Assert; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.util.MultiValueMap; -import org.springframework.web.util.UriComponentsBuilder; -import java.net.URL; import java.util.*; /** diff --git a/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java index 66f3f4715..2a6af22ff 100644 --- a/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java +++ b/test/src/test/java/com/alibaba/nacos/test/naming/RestAPI_ITCase.java @@ -19,8 +19,8 @@ import java.net.URL; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; -import com.alibaba.nacos.naming.NamingApp; +import com.alibaba.nacos.naming.NamingApp; import com.alibaba.nacos.test.base.Params; import org.junit.After; import org.junit.Assert; diff --git a/test/src/test/java/com/alibaba/nacos/test/smoke/nacosSmoke_ITCase.java b/test/src/test/java/com/alibaba/nacos/test/smoke/nacosSmoke_ITCase.java index f0a0ac22f..650b4bb4b 100644 --- a/test/src/test/java/com/alibaba/nacos/test/smoke/nacosSmoke_ITCase.java +++ b/test/src/test/java/com/alibaba/nacos/test/smoke/nacosSmoke_ITCase.java @@ -37,6 +37,5 @@ public class nacosSmoke_ITCase { @Test public void testSmoke() { - logger.info("nacosSmoke_ITCase :testSmoke"); } } diff --git a/test/src/test/resources/application.properties b/test/src/test/resources/application.properties index adb20a5e3..2dca8441e 100644 --- a/test/src/test/resources/application.properties +++ b/test/src/test/resources/application.properties @@ -26,10 +26,14 @@ nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/ nacos.core.auth.system.type=nacos ### If turn on auth system: -nacos.core.auth.enabled=false +nacos.core.auth.enabled=true + +nacos.core.auth.caching.enabled=false ### The token expiration in seconds: nacos.core.auth.default.token.expire.seconds=18000 ### The default token: nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789 + +tldSkipPatterns=derbyLocale_*.jar,jaxb-api.jar,jsr173_1.0_api.jar,jaxb1-impl.jar,activation.jar diff --git a/test/src/test/resources/schema.sql b/test/src/test/resources/schema.sql index b8419a380..5842a2267 100644 --- a/test/src/test/resources/schema.sql +++ b/test/src/test/resources/schema.sql @@ -1,4 +1,4 @@ -CREATE SCHEMA diamond AUTHORIZATION diamond; +CREATE SCHEMA nacos AUTHORIZATION nacos; CREATE TABLE config_info ( id bigint NOT NULL generated by default as identity, @@ -159,17 +159,38 @@ CREATE TABLE tenant_capacity ( constraint tenant_capacity_id_key PRIMARY KEY (id), constraint uk_tenant_id UNIQUE (tenant_id)); +CREATE TABLE tenant_info ( + id bigint NOT NULL generated by default as identity, + kp varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + tenant_name varchar(128) DEFAULT '', + tenant_desc varchar(256) DEFAULT NULL, + create_source varchar(32) DEFAULT NULL, + gmt_create bigint NOT NULL, + gmt_modified bigint NOT NULL, + constraint tenant_info_id_key PRIMARY KEY (id), + constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); +CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id); + CREATE TABLE users ( username varchar(50) NOT NULL PRIMARY KEY, password varchar(500) NOT NULL, - enabled boolean NOT NULL + enabled boolean NOT NULL DEFAULT true ); CREATE TABLE roles ( username varchar(50) NOT NULL, - role varchar(50) NOT NULL + role varchar(50) NOT NULL, + constraint uk_username_role UNIQUE (username,role) +); + +CREATE TABLE permissions ( + role varchar(50) NOT NULL, + resource varchar(512) NOT NULL, + action varchar(8) NOT NULL, + constraint uk_role_permission UNIQUE (role,resource,action) ); INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE); -INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN'); +INSERT INTO roles (username, role) VALUES ('nacos', 'GLOBAL_ADMIN');