You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by xx...@apache.org on 2023/01/06 11:10:15 UTC
[kylin] 10/12: KYLIN-5356 Backend configuration of users supports the project administrator role
This is an automated email from the ASF dual-hosted git repository.
xxyu pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git
commit be5e5fa209fb26f8f5747ca3469403a46c8c6a13
Author: Liang.Hua <36...@users.noreply.github.com>
AuthorDate: Mon Oct 31 15:50:44 2022 +0800
KYLIN-5356 Backend configuration of users supports the project administrator role
---
.../rest/response/OpenAccessGroupResponse.java | 40 +++++++
.../rest/response/OpenAccessUserResponse.java | 40 +++++++
.../rest/controller/v2/NAccessControllerV2.java | 124 ++++++++++++++++++--
.../rest/controller/NAccessControllerV2Test.java | 125 ++++++++++++++++++++-
4 files changed, 316 insertions(+), 13 deletions(-)
diff --git a/src/common-service/src/main/java/org/apache/kylin/rest/response/OpenAccessGroupResponse.java b/src/common-service/src/main/java/org/apache/kylin/rest/response/OpenAccessGroupResponse.java
new file mode 100644
index 0000000000..96042b432f
--- /dev/null
+++ b/src/common-service/src/main/java/org/apache/kylin/rest/response/OpenAccessGroupResponse.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.kylin.rest.response;
+
+import java.util.List;
+
+import org.apache.kylin.common.util.Pair;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class OpenAccessGroupResponse {
+
+ @JsonProperty("groups")
+ private List<Pair<String, Integer>> groups;
+
+ @JsonProperty("size")
+ private int size;
+}
diff --git a/src/common-service/src/main/java/org/apache/kylin/rest/response/OpenAccessUserResponse.java b/src/common-service/src/main/java/org/apache/kylin/rest/response/OpenAccessUserResponse.java
new file mode 100644
index 0000000000..c7f046bc57
--- /dev/null
+++ b/src/common-service/src/main/java/org/apache/kylin/rest/response/OpenAccessUserResponse.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.kylin.rest.response;
+
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import org.apache.kylin.metadata.user.ManagedUser;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class OpenAccessUserResponse {
+
+ @JsonProperty("users")
+ private List<ManagedUser> users;
+
+ @JsonProperty("size")
+ private int size;
+}
diff --git a/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/v2/NAccessControllerV2.java b/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/v2/NAccessControllerV2.java
index 2b9f9d2f4b..e4465dd69f 100644
--- a/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/v2/NAccessControllerV2.java
+++ b/src/metadata-server/src/main/java/org/apache/kylin/rest/controller/v2/NAccessControllerV2.java
@@ -17,8 +17,8 @@
*/
package org.apache.kylin.rest.controller.v2;
-import static org.apache.kylin.common.exception.ServerErrorCode.USER_NOT_EXIST;
import static org.apache.kylin.common.constant.HttpConstant.HTTP_VND_APACHE_KYLIN_V2_JSON;
+import static org.apache.kylin.common.exception.ServerErrorCode.USER_NOT_EXIST;
import java.io.IOException;
import java.util.ArrayList;
@@ -26,22 +26,35 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import java.util.stream.Collectors;
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.KylinConfig;
import org.apache.kylin.common.exception.KylinException;
import org.apache.kylin.common.persistence.AclEntity;
+import org.apache.kylin.common.util.Pair;
import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.project.NProjectManager;
+import org.apache.kylin.metadata.project.ProjectInstance;
import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.controller.NBasicController;
import org.apache.kylin.rest.response.AccessEntryResponse;
import org.apache.kylin.rest.response.EnvelopeResponse;
+import org.apache.kylin.rest.response.OpenAccessGroupResponse;
+import org.apache.kylin.rest.response.OpenAccessUserResponse;
+import org.apache.kylin.rest.security.AclEntityType;
import org.apache.kylin.rest.service.AccessService;
+import org.apache.kylin.rest.service.AclTCRService;
+import org.apache.kylin.rest.service.IUserGroupService;
import org.apache.kylin.rest.service.UserService;
+import org.apache.kylin.rest.util.AclEvaluate;
import org.apache.kylin.rest.util.PagingUtil;
-import org.apache.kylin.rest.controller.NBasicController;
-import org.apache.kylin.rest.service.AclTCRService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -49,6 +62,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import org.apache.kylin.metadata.user.ManagedUser;
import io.swagger.annotations.ApiOperation;
@Controller
@@ -63,18 +80,26 @@ public class NAccessControllerV2 extends NBasicController {
@Qualifier("userService")
protected UserService userService;
+ @Autowired
+ @Qualifier("userGroupService")
+ private IUserGroupService userGroupService;
+
@Autowired
@Qualifier("aclTCRService")
private AclTCRService aclTCRService;
+ @Autowired
+ private AclEvaluate aclEvaluate;
+
private static final String PROJECT_NAME = "project_name";
private static final String TABLE_NAME = "table_name";
- private void checkUserName(String userName) {
+ private ManagedUser checkAndGetUser(String userName) {
if (!userService.userExists(userName)) {
throw new KylinException(USER_NOT_EXIST,
String.format(Locale.ROOT, "User '%s' does not exists.", userName));
}
+ return (ManagedUser) userService.loadUserByUsername(userName);
}
/**
@@ -89,7 +114,7 @@ public class NAccessControllerV2 extends NBasicController {
@ResponseBody
@PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
public EnvelopeResponse getAllAccessEntitiesOfUser(@PathVariable("userName") String username) throws IOException {
- checkUserName(username);
+ checkAndGetUser(username);
List<Object> dataList = new ArrayList<>();
List<String> projectList = accessService.getGrantedProjectsOfUser(username);
@@ -115,13 +140,92 @@ public class NAccessControllerV2 extends NBasicController {
@RequestParam(value = "pageOffset", required = false, defaultValue = "0") Integer pageOffset,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize)
throws IOException {
- AclEntity ae = accessService.getAclEntity(type, getProject(project).getUuid());
- List<AccessEntryResponse> resultsAfterFuzzyMatching = this.accessService.generateAceResponsesByFuzzMatching(ae,
- nameSeg, isCaseSensitive);
- List<AccessEntryResponse> sublist = PagingUtil.cutPage(resultsAfterFuzzyMatching, pageOffset, pageSize);
+ List<AccessEntryResponse> accessList = getAccessList(type, project, nameSeg, isCaseSensitive);
+ List<AccessEntryResponse> sublist = PagingUtil.cutPage(accessList, pageOffset, pageSize);
HashMap<String, Object> data = new HashMap<>();
data.put("sids", sublist);
- data.put("size", resultsAfterFuzzyMatching.size());
+ data.put("size", accessList.size());
return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, data, "");
}
+
+ @ApiOperation(value = "getAllAccessUsers", tags = { "MID" })
+ @GetMapping(value = "/all/users", produces = { HTTP_VND_APACHE_KYLIN_V2_JSON })
+ @ResponseBody
+ public EnvelopeResponse<OpenAccessUserResponse> getAllAccessUsers(
+ @RequestParam(value = "project", required = false) String project,
+ @RequestParam(value = "userName", required = false) String userName,
+ @RequestParam(value = "pageOffset", required = false, defaultValue = "0") Integer pageOffset,
+ @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize)
+ throws IOException {
+ Set<ManagedUser> users = StringUtils.isNotEmpty(userName) ? Sets.newHashSet(checkAndGetUser(userName))
+ : getUsersOfProjects(getGrantedProjects(project));
+ return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, new OpenAccessUserResponse(
+ PagingUtil.cutPage(Lists.newArrayList(users), pageOffset, pageSize), users.size()), "");
+ }
+
+ @ApiOperation(value = "getAllAccessGroups", tags = { "MID" })
+ @GetMapping(value = "/all/groups", produces = { HTTP_VND_APACHE_KYLIN_V2_JSON })
+ @ResponseBody
+ public EnvelopeResponse<OpenAccessGroupResponse> getAllAccessGroups(
+ @RequestParam(value = "project", required = false) String project,
+ @RequestParam(value = "groupName", required = false) String groupName,
+ @RequestParam(value = "pageOffset", required = false, defaultValue = "0") Integer pageOffset,
+ @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize)
+ throws IOException {
+ List<Pair<String, Integer>> result = StringUtils.isNotEmpty(groupName)
+ ? Lists.newArrayList(Pair.newPair(groupName, userGroupService.getGroupMembersByName(groupName).size()))
+ : getUserGroupsOfProjects(getGrantedProjects(project));
+ return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, new OpenAccessGroupResponse(
+ PagingUtil.cutPage(Lists.newArrayList(result), pageOffset, pageSize), result.size()), "");
+ }
+
+ private List<AccessEntryResponse> getAccessList(String type, String projectName, String nameSeg,
+ boolean isCaseSensitive) throws IOException {
+ AclEntity aclEntity = accessService.getAclEntity(type, getProject(projectName).getUuid());
+ return this.accessService.generateAceResponsesByFuzzMatching(aclEntity, nameSeg, isCaseSensitive);
+ }
+
+ private List<String> getGrantedProjects(String projectName) {
+ NProjectManager projectManager = NProjectManager.getInstance(KylinConfig.getInstanceFromEnv());
+ if (StringUtils.isBlank(projectName)) {
+ return projectManager.listAllProjects().stream().map(ProjectInstance::getName)
+ .filter(name -> aclEvaluate.hasProjectAdminPermission(name)).collect(Collectors.toList());
+ } else if (aclEvaluate.hasProjectReadPermission(projectManager.getProject(projectName))) {
+ return Lists.newArrayList(projectName);
+ }
+ return Lists.newArrayList();
+ }
+
+ private Set<ManagedUser> getUsersOfProjects(List<String> projects) throws IOException {
+ Set<ManagedUser> allUsers = Sets.newHashSet();
+ for (String projectName : projects) {
+ List<AccessEntryResponse> responses = getAccessList(AclEntityType.PROJECT_INSTANCE, projectName, null,
+ false);
+ allUsers.addAll(responses.stream().filter(response -> response.getSid() instanceof PrincipalSid)
+ .map(response -> (ManagedUser) userService
+ .loadUserByUsername(((PrincipalSid) response.getSid()).getPrincipal()))
+ .collect(Collectors.toSet()));
+ }
+ return allUsers;
+ }
+
+ private List<Pair<String, Integer>> getUserGroupsOfProjects(List<String> projects) throws IOException {
+ List<Pair<String, Integer>> allUserGroups = Lists.newArrayList();
+ List<String> grantedGroups = Lists.newArrayList();
+ for (String projectName : projects) {
+ List<AccessEntryResponse> responses = getAccessList(AclEntityType.PROJECT_INSTANCE, projectName, null,
+ false);
+ for (AccessEntryResponse response : responses) {
+ if (response.getSid() instanceof GrantedAuthoritySid) {
+ String grantedAuthority = ((GrantedAuthoritySid) response.getSid()).getGrantedAuthority();
+ if (!grantedGroups.contains(grantedAuthority)) {
+ grantedGroups.add(grantedAuthority);
+ allUserGroups.add(Pair.newPair(grantedAuthority,
+ userGroupService.getGroupMembersByName(grantedAuthority).size()));
+ }
+ }
+ }
+ }
+ return allUserGroups;
+ }
}
diff --git a/src/metadata-server/src/test/java/org/apache/kylin/rest/controller/NAccessControllerV2Test.java b/src/metadata-server/src/test/java/org/apache/kylin/rest/controller/NAccessControllerV2Test.java
index 6aae71d82b..526ab7251d 100644
--- a/src/metadata-server/src/test/java/org/apache/kylin/rest/controller/NAccessControllerV2Test.java
+++ b/src/metadata-server/src/test/java/org/apache/kylin/rest/controller/NAccessControllerV2Test.java
@@ -19,12 +19,30 @@ package org.apache.kylin.rest.controller;
import static org.apache.kylin.common.constant.HttpConstant.HTTP_VND_APACHE_KYLIN_V2_JSON;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.kylin.common.persistence.AclEntity;
+import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.common.util.NLocalFileMetadataTestCase;
+import org.apache.kylin.metadata.project.NProjectManager;
+import org.apache.kylin.metadata.project.ProjectInstance;
import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.service.AccessService;
-import org.apache.kylin.rest.service.UserService;
import org.apache.kylin.rest.controller.v2.NAccessControllerV2;
+import org.apache.kylin.rest.response.AccessEntryResponse;
+import org.apache.kylin.rest.response.EnvelopeResponse;
+import org.apache.kylin.rest.response.OpenAccessGroupResponse;
+import org.apache.kylin.rest.response.OpenAccessUserResponse;
+import org.apache.kylin.rest.security.AclEntityType;
+import org.apache.kylin.rest.service.AccessService;
import org.apache.kylin.rest.service.AclTCRService;
+import org.apache.kylin.rest.service.IUserGroupService;
+import org.apache.kylin.rest.service.ProjectService;
+import org.apache.kylin.rest.service.UserService;
+import org.apache.kylin.rest.util.AclEvaluate;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
@@ -32,8 +50,11 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.http.MediaType;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@@ -42,7 +63,9 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.google.common.collect.Lists;
-public class NAccessControllerV2Test {
+import org.apache.kylin.metadata.user.ManagedUser;
+
+public class NAccessControllerV2Test extends NLocalFileMetadataTestCase {
private MockMvc mockMvc;
@@ -55,6 +78,15 @@ public class NAccessControllerV2Test {
@Mock
private AclTCRService aclTCRService;
+ @Mock
+ private AclEvaluate aclEvaluate;
+
+ @Mock
+ private ProjectService projectService;
+
+ @Mock
+ private IUserGroupService userGroupService;
+
@InjectMocks
private NAccessControllerV2 nAccessControllerV2 = Mockito.spy(new NAccessControllerV2());
@@ -67,10 +99,12 @@ public class NAccessControllerV2Test {
.defaultRequest(MockMvcRequestBuilders.get("/")).build();
SecurityContextHolder.getContext().setAuthentication(authentication);
+ createTestMetadata();
}
@After
public void tearDown() {
+ cleanupTestMetadata();
}
@Test
@@ -88,4 +122,89 @@ public class NAccessControllerV2Test {
Mockito.verify(nAccessControllerV2).getAllAccessEntitiesOfUser(userName);
}
+ @Test
+ public void testGetAllAccessUsers() throws Exception {
+ String project = "default";
+ String userName = "user01";
+ mockMvc.perform(MockMvcRequestBuilders.get("/api/access/all/users").contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V2_JSON)))
+ .andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
+
+ Mockito.verify(nAccessControllerV2).getAllAccessUsers(null, null, 0, 10);
+
+ Mockito.doNothing().when(aclEvaluate).checkProjectAdminPermission(project);
+ mockMvc.perform(MockMvcRequestBuilders.get("/api/access/all/users").param("project", project)
+ .param("userName", userName).contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V2_JSON)))
+ .andExpect(MockMvcResultMatchers.status().is5xxServerError()).andReturn();
+
+ Mockito.verify(nAccessControllerV2).getAllAccessUsers(project, userName, 0, 10);
+
+ List<GrantedAuthority> authorities = new ArrayList<>();
+ ManagedUser user = new ManagedUser(userName, "123", false, authorities);
+ Authentication authentication = new TestingAuthenticationToken(user, userName, Constant.ROLE_ADMIN);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ Mockito.doReturn(user).when(userService).loadUserByUsername(userName);
+ try {
+ nAccessControllerV2.getAllAccessUsers(project, userName, 0, 10);
+ } catch (Exception e) {
+ Assert.assertEquals(String.format(Locale.ROOT, "User '%s' does not exists.", userName), e.getMessage());
+ }
+
+ ProjectInstance projectInstance = NProjectManager.getInstance(getTestConfig()).getProject(project);
+ Mockito.doReturn(Lists.newArrayList(projectInstance)).when(projectService).getReadableProjects(project, true);
+ AccessEntryResponse accessEntryResponse = Mockito.mock(AccessEntryResponse.class);
+ AclEntity aclEntity = Mockito.mock(RootPersistentEntity.class);
+ PrincipalSid principalSid = Mockito.mock(PrincipalSid.class);
+ Mockito.doReturn(principalSid).when(accessEntryResponse).getSid();
+ Mockito.doReturn(userName).when(principalSid).getPrincipal();
+ Mockito.doReturn(aclEntity).when(accessService).getAclEntity(AclEntityType.PROJECT_INSTANCE,
+ projectInstance.getUuid());
+ Mockito.doReturn(Lists.newArrayList(accessEntryResponse)).when(accessService)
+ .generateAceResponsesByFuzzMatching(aclEntity, null, false);
+ EnvelopeResponse<OpenAccessUserResponse> envelopeResponse1 = nAccessControllerV2.getAllAccessUsers(project,
+ null, 0, 10);
+ Assert.assertNotNull(envelopeResponse1.getData());
+ }
+
+ @Test
+ public void testGetAllAccessGroups() throws Exception {
+ String project = "default";
+ String groupName = "group01";
+ mockMvc.perform(MockMvcRequestBuilders.get("/api/access/all/groups").contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V2_JSON)))
+ .andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
+ Mockito.verify(nAccessControllerV2).getAllAccessGroups(null, null, 0, 10);
+
+ mockMvc.perform(MockMvcRequestBuilders.get("/api/access/all/groups").param("project", project)
+ .param("groupName", groupName).contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V2_JSON)))
+ .andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
+
+ Mockito.verify(nAccessControllerV2).getAllAccessGroups(project, groupName, 0, 10);
+
+ List<GrantedAuthority> authorities = new ArrayList<>();
+ ManagedUser user = new ManagedUser("user", "123", false, authorities);
+ Authentication authentication = new TestingAuthenticationToken(user, "user", Constant.ROLE_ADMIN);
+ Mockito.doReturn(Lists.newArrayList(user)).when(userGroupService).getGroupMembersByName(groupName);
+ EnvelopeResponse<OpenAccessGroupResponse> envelopeResponse = nAccessControllerV2.getAllAccessGroups(project,
+ groupName, 0, 10);
+ Assert.assertNotNull(envelopeResponse.getData());
+
+ ProjectInstance projectInstance = NProjectManager.getInstance(getTestConfig()).getProject(project);
+ Mockito.doReturn(Lists.newArrayList(projectInstance)).when(projectService).getReadableProjects(project, true);
+ AccessEntryResponse accessEntryResponse = Mockito.mock(AccessEntryResponse.class);
+ AclEntity aclEntity = Mockito.mock(RootPersistentEntity.class);
+ GrantedAuthoritySid grantedAuthoritySid = Mockito.mock(GrantedAuthoritySid.class);
+ Mockito.doReturn(grantedAuthoritySid).when(accessEntryResponse).getSid();
+ Mockito.doReturn(groupName).when(grantedAuthoritySid).getGrantedAuthority();
+ Mockito.doReturn(aclEntity).when(accessService).getAclEntity(AclEntityType.PROJECT_INSTANCE,
+ projectInstance.getUuid());
+ Mockito.doReturn(Lists.newArrayList(accessEntryResponse)).when(accessService)
+ .generateAceResponsesByFuzzMatching(aclEntity, null, false);
+ EnvelopeResponse<OpenAccessGroupResponse> envelopeResponse1 = nAccessControllerV2.getAllAccessGroups(project,
+ null, 0, 10);
+ Assert.assertNotNull(envelopeResponse1.getData());
+ }
+
}