Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(collaboration): support for configuring database administrators and participating in approvals #2168

Merged
merged 8 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client
Submodule client updated 45 files
+16 −0 src/common/network/projectNotification.ts
+16 −0 src/component/Input/Case/index.tsx
+16 −0 src/component/Input/Keymap/index.tsx
+16 −0 src/component/Input/Keymap/keycodemap.ts
+16 −0 src/component/MonacoEditor/DiffEditor.tsx
+16 −0 src/component/MonacoEditor/config.ts
+16 −0 src/component/MonacoEditor/plugins/theme/github.ts
+16 −0 src/component/MonacoEditor/plugins/theme/index.ts
+16 −0 src/component/MonacoEditor/plugins/theme/monokai.ts
+16 −0 src/component/ODCSetting/Item/InputItem.tsx
+16 −0 src/component/ODCSetting/Item/RadioItem.tsx
+16 −0 src/component/ODCSetting/Item/SelectItem.tsx
+16 −0 src/component/ODCSetting/Item/TextItem.tsx
+16 −0 src/component/ODCSetting/config.tsx
+16 −0 src/component/ODCSetting/config/account.tsx
+16 −0 src/component/ODCSetting/config/database.tsx
+16 −0 src/component/ODCSetting/config/editor.tsx
+16 −0 src/component/ODCSetting/config/performance.tsx
+16 −0 src/component/ODCSetting/config/preference.tsx
+16 −0 src/component/ODCSetting/index.tsx
+16 −0 src/component/Task/StructureComparisonTask/CreateModal/TableSelector.tsx
+16 −0 src/component/Task/StructureComparisonTask/CreateModal/index.tsx
+16 −0 src/component/Task/StructureComparisonTask/CreateModal/interface.ts
+16 −0 src/component/Task/component/PartitionPolicyFormTable/EditTable/index.tsx
+16 −0 src/component/Task/component/PartitionPolicyFormTable/RuleFormItem/index.tsx
+16 −0 src/component/Task/component/PartitionPolicyFormTable/const.ts
+16 −0 src/component/Task/const.ts
+16 −0 src/component/Task/hooks/useProjects.tsx
+16 −0 src/d.ts/projectNotification.ts
+16 −0 src/d.ts/task.ts
+2 −0 src/page/Datasource/Info/NewDataBaseButton/index.tsx
+16 −0 src/page/Login/components/LDAPModal/index.tsx
+16 −0 src/page/Project/Database/StatusName.tsx
+16 −0 src/page/Project/Notification/components/Channel.tsx
+16 −0 src/page/Project/Notification/components/Message.tsx
+16 −0 src/page/Project/Notification/components/MessageStatus.tsx
+16 −0 src/page/Project/Notification/components/Policy.tsx
+16 −0 src/page/Project/Notification/components/columns.tsx
+16 −0 src/page/Project/Notification/components/interface.ts
+16 −0 src/page/Secure/Env/components/FormEnvironmentModal.tsx
+16 −0 src/page/Workspace/components/SessionContextWrap/SessionSelect/SelectItem.tsx
+16 −0 src/page/Workspace/components/SessionContextWrap/SessionSelect/const.ts
+16 −0 src/util/broadcastChannel.ts
+16 −0 src/util/sentry.ts
+16 −0 src/util/versionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ public void testCreateProject_Success() {
@Test
public void testGetProject_Success() {
Project saved = projectService.create(getProject());
Mockito.when(resourceRoleService.listByResourceId(Mockito.any()))
Mockito.when(
resourceRoleService.listByResourceTypeAndId(Mockito.eq(ResourceType.ODC_PROJECT), Mockito.anyLong()))
.thenReturn(listUserResourceRole(saved.getId()));
Project actual = projectService.detail(saved.getId());
Assert.assertNotNull(actual);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,13 @@ public void testFindById_Success() {
public void testTransfer_Success() {
Mockito.when(connectionService.checkPermission(Mockito.anyList(), Mockito.anyList())).thenReturn(true);
Mockito.when(projectPermissionValidator.hasProjectRole(Mockito.anyList(), Mockito.anyList())).thenReturn(true);
databaseRepository.saveAndFlush(getEntity());
DatabaseEntity saved = databaseRepository.saveAndFlush(getEntity());
TransferDatabasesReq req = new TransferDatabasesReq();
req.setDatabaseIds(Arrays.asList(1L));
req.setDatabaseIds(Arrays.asList(saved.getId()));
req.setProjectId(2L);
Assert.assertTrue(databaseService.transfer(req));
Assert.assertEquals(2L, databaseRepository.findById(1L).get().getProjectId().longValue());
Assert.assertEquals(2L, databaseRepository.findById(saved.getId()).get().getProjectId().longValue());

}

private DatabaseEntity getEntity() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ public void testSaveAll_Success() {
Mockito.when(resourceRoleRepository.findAll()).thenReturn(getResourceRoleEntity());
Mockito.when(resourceRoleRepository.findById(1L)).thenReturn(Optional.of(getResourceRoleEntity().get(0)));
Mockito.when(authenticationFacade.currentOrganizationId()).thenReturn(1L);

resourceRoleService.saveAll(Arrays.asList(getProjectOwner()));

int actual = userResourceRoleRepository.findByUserId(1L).size();
Assert.assertEquals(1, actual);
}
Expand All @@ -83,8 +81,7 @@ public void testListByResourceId_Success() {
.thenReturn(Optional.of(getResourceRoleEntity().get(0)));
Mockito.when(authenticationFacade.currentOrganizationId()).thenReturn(1L);
resourceRoleService.saveAll(Arrays.asList(getProjectOwner()));

int actual = resourceRoleService.listByResourceId(1L).size();
int actual = resourceRoleService.listByResourceTypeAndId(ResourceType.ODC_PROJECT, 1L).size();
Assert.assertEquals(1, actual);
}

Expand All @@ -94,7 +91,6 @@ public void testListByOrganizationIdAndUserId_Success() {
Mockito.when(resourceRoleRepository.findById(1L)).thenReturn(Optional.of(getResourceRoleEntity().get(0)));
Mockito.when(authenticationFacade.currentOrganizationId()).thenReturn(1L);
resourceRoleService.saveAll(Arrays.asList(getProjectOwner()));

int actual = resourceRoleService.listByOrganizationIdAndUserId(1L, 1L).size();
Assert.assertEquals(1, actual);
}
Expand All @@ -105,15 +101,15 @@ public void testDeleteById_Success() {
Mockito.when(resourceRoleRepository.findById(1L)).thenReturn(Optional.of(getResourceRoleEntity().get(0)));
Mockito.when(authenticationFacade.currentOrganizationId()).thenReturn(1L);
resourceRoleService.saveAll(Arrays.asList(getProjectOwner()));

int actual = resourceRoleService.deleteByResourceId(1L);
int actual = userResourceRoleRepository.deleteByResourceId(1L);
Assert.assertEquals(1, actual);
}

private UserResourceRole getProjectOwner() {
UserResourceRole projectOwner = new UserResourceRole();
projectOwner.setUserId(1L);
projectOwner.setResourceId(1L);
projectOwner.setResourceType(ResourceType.ODC_PROJECT);
projectOwner.setResourceRole(ResourceRoleName.OWNER);
return projectOwner;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,14 @@ public static boolean startsWithIgnoreSpaceAndNewLines(@NonNull String target, @
return matchLength >= maxMatchLength || j >= prefixes.length;
}

public static boolean isTranslatable(@NonNull String str) {
return str.startsWith(DEFAULT_VARIABLE_PREFIX) && str.endsWith(DEFAULT_VARIABLE_SUFFIX);
}

public static String getTranslatableKey(@NonNull String str) {
if (!isTranslatable(str)) {
throw new IllegalStateException(str + " is not translatable");
}
return str.substring(DEFAULT_VARIABLE_PREFIX.length(), str.length() - DEFAULT_VARIABLE_SUFFIX.length());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
kind: resource
version: v2
templates:
- metadata:
allow_duplicate: false
table_name: iam_resource_role
unique_keys: [ "resource_type", "role_name" ]
specs:
- column_name: id
default_value: 6
data_type: java.lang.Long
- column_name: resource_type
value: "ODC_DATABASE"
- column_name: role_name
value: "OWNER"
- column_name: description
value: "built-in resource role, database owner"
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.oceanbase.odc.service.connection.database.model.CreateDatabaseReq;
import com.oceanbase.odc.service.connection.database.model.Database;
import com.oceanbase.odc.service.connection.database.model.DeleteDatabasesReq;
import com.oceanbase.odc.service.connection.database.model.ModifyDatabaseOwnerReq;
import com.oceanbase.odc.service.connection.database.model.QueryDatabaseParams;
import com.oceanbase.odc.service.connection.database.model.TransferDatabasesReq;

Expand Down Expand Up @@ -103,4 +104,11 @@ public SuccessResponse<Boolean> transferDatabase(@RequestBody TransferDatabasesR
public SuccessResponse<Boolean> deleteDatabases(@RequestBody DeleteDatabasesReq req) {
return Responses.success(databaseService.deleteDatabases(req));
}

@ApiOperation(value = "modifyDatabasesOwner", notes = "modify database owner")
@RequestMapping(value = "/databases/owner/{projectId:[\\d]+}", method = RequestMethod.PUT)
public SuccessResponse<Boolean> modifyDatabasesOwners(@PathVariable Long projectId,
@RequestBody ModifyDatabaseOwnerReq req) {
return Responses.success(databaseService.modifyDatabasesOwners(projectId, req));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

import com.oceanbase.odc.common.json.JsonUtils;
import com.oceanbase.odc.core.shared.constant.ErrorCodes;
import com.oceanbase.odc.core.shared.constant.ResourceType;
import com.oceanbase.odc.core.shared.exception.BadRequestException;
import com.oceanbase.odc.service.captcha.CaptchaService;
import com.oceanbase.odc.service.captcha.VerificationCode;
Expand Down Expand Up @@ -331,8 +332,10 @@ public PaginatedResponse<Role> listRoles(

@ApiOperation(value = "listResourceRoles", notes = "list resource roles")
@RequestMapping(value = "/resourceRoles", method = RequestMethod.GET)
public ListResponse<ResourceRole> listResourceRoles() {
return Responses.list(resourceRoleService.listResourceRoles());
public ListResponse<ResourceRole> listResourceRoles(
@RequestParam(required = false, value = "resourceType",
defaultValue = "ODC_PROJECT") List<ResourceType> resourceType) {
return Responses.list(resourceRoleService.listResourceRoles(resourceType));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import com.oceanbase.odc.metadb.collaboration.ProjectEntity;
import com.oceanbase.odc.metadb.collaboration.ProjectRepository;
import com.oceanbase.odc.service.collaboration.environment.EnvironmentService;
import com.oceanbase.odc.service.collaboration.project.ProjectService;
import com.oceanbase.odc.service.config.UserConfigService;
import com.oceanbase.odc.service.connection.ConnectionService;
import com.oceanbase.odc.service.connection.model.ConnectionConfig;
Expand Down Expand Up @@ -71,9 +70,6 @@ public class HookConfiguration {
@Autowired
private RiskLevelService riskLevelService;

@Autowired
private ProjectService projectService;

@Autowired
private ResourceRoleService resourceRoleService;

Expand All @@ -96,7 +92,7 @@ public class HookConfiguration {
public void init() {
userService.addPostUserDeleteHook(event -> {
Long userId = event.getUserId();
projectService.deleteUserRelatedProjectRoles(userId);
resourceRoleService.deleteByUserId(userId);
userConfigService.deleteUserConfigurations(userId);
});
log.info("PostUserDeleteHook added");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ public interface ResourceRoleRepository

List<ResourceRoleEntity> findByResourceType(ResourceType resourceType);

List<ResourceRoleEntity> findByResourceTypeIn(List<ResourceType> resourceType);

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,50 +18,110 @@
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

public interface UserResourceRoleRepository
extends JpaRepository<UserResourceRoleEntity, Long>, JpaSpecificationExecutor<UserResourceRoleEntity> {
List<UserResourceRoleEntity> findByOrganizationIdAndUserId(Long organizationId, Long userId);
import com.oceanbase.odc.common.jpa.InsertSqlTemplateBuilder;
import com.oceanbase.odc.config.jpa.OdcJpaRepository;
import com.oceanbase.odc.core.shared.constant.ResourceType;

public interface UserResourceRoleRepository extends OdcJpaRepository<UserResourceRoleEntity, Long> {

List<UserResourceRoleEntity> findByOrganizationIdAndUserId(Long organizationId, Long userId);

List<UserResourceRoleEntity> findByUserId(Long userId);

List<UserResourceRoleEntity> findByResourceId(Long resourceId);

List<UserResourceRoleEntity> findByResourceIdIn(Collection<Long> resourceIds);

@Modifying
@Transactional
@Query(value = "delete from iam_user_resource_role t where t.user_id =:userId", nativeQuery = true)
int deleteByUserId(@Param("userId") Long userId);

@Query(nativeQuery = true,
value = "select t.* from iam_user_resource_role t where concat(t.resource_id, ':', t.resource_role_id) in (:resourceRoleIdentifiers)")
List<UserResourceRoleEntity> findByResourceIdsAndResourceRoleIdsIn(
@Param("resourceRoleIdentifiers") Set<String> resourceRoleIdentifiers);


@Modifying
@Transactional
@Query(value = "delete from iam_user_resource_role t where t.resource_id =:resourceId", nativeQuery = true)
int deleteByResourceId(@Param("resourceId") Long resourceId);

@Modifying
@Transactional
@Query(value = "delete from iam_user_resource_role t where t.resource_id =:resourceId and t.user_id =:userId",
@Query(value = "delete from iam_user_resource_role i_urr where i_urr.resource_id = :resourceId and i_urr.resource_role_id "
+ "in (select i_rr.id from iam_resource_role i_rr where i_rr.resource_type = :#{#resourceType.name()})",
nativeQuery = true)
int deleteByResourceTypeAndId(@Param("resourceType") ResourceType resourceType,
@Param("resourceId") Long resourceId);

@Modifying
@Transactional
@Query(value = "delete from iam_user_resource_role i_urr where i_urr.resource_id in (:resourceIds) and i_urr.resource_role_id "
+ "in (select i_rr.id from iam_resource_role i_rr where i_rr.resource_type = :#{#resourceType.name()})",
nativeQuery = true)
int deleteByResourceIdAndUserId(@Param("resourceId") Long resourceId, @Param("userId") Long userId);
int deleteByResourceTypeAndIdIn(@Param("resourceType") ResourceType resourceType,
@Param("resourceIds") Collection<Long> resourceIds);

@Modifying
@Transactional
@Query(value = "delete from iam_user_resource_role t where t.resource_id in (:resourceIds) and t.user_id =:userId",
@Query(value = "delete from iam_user_resource_role i_urr where i_urr.user_id = :userId and i_urr.resource_id = :resourceId "
+ "and i_urr.resource_role_id in (select i_rr.id from iam_resource_role i_rr where i_rr.resource_type = :#{#resourceType.name()})",
nativeQuery = true)
int deleteByUserIdAndResourceIdIn(@Param("userId") Long userId, @Param("resourceIds") Set<Long> resourceIds);
int deleteByUserIdAndResourceIdAndResourceType(@Param("userId") Long userId, @Param("resourceId") Long resourceId,
@Param("resourceType") ResourceType resourceType);

@Modifying
@Transactional
@Query(value = "delete from iam_user_resource_role i_urr where i_urr.user_id = :userId and i_urr.resource_id in (:resourceIds) "
+ "and i_urr.resource_role_id in (select i_rr.id from iam_resource_role i_rr where i_rr.resource_type = :#{#resourceType.name()})",
nativeQuery = true)
int deleteByUserIdAndResourceIdInAndResourceType(@Param("userId") Long userId,
@Param("resourceIds") Collection<Long> resourceIds, @Param("resourceType") ResourceType resourceType);

@Query(nativeQuery = true,
value = "select t.* from iam_user_resource_role t where concat(t.resource_id, ':', t.resource_role_id) in (:resourceRoleIdentifiers)")
List<UserResourceRoleEntity> findByResourceIdsAndResourceRoleIdsIn(
@Param("resourceRoleIdentifiers") Set<String> resourceRoleIdentifiers);

@Query(value = "select i_urr.* from iam_user_resource_role i_urr inner join iam_resource_role i_rr on "
+ "i_urr.resource_role_id = i_rr.id where i_rr.resource_type = :#{#resourceType.name()} and i_urr.resource_id = :resourceId",
nativeQuery = true)
List<UserResourceRoleEntity> listByResourceTypeAndId(
@Param("resourceType") ResourceType resourceType, @Param("resourceId") Long resourceId);

@Query(value = "select i_urr.* from iam_user_resource_role i_urr inner join iam_resource_role i_rr on "
+ "i_urr.resource_role_id = i_rr.id where i_rr.resource_type = :#{#resourceType.name()} and i_urr.resource_id in (:resourceIds)",
nativeQuery = true)
List<UserResourceRoleEntity> listByResourceTypeAndIdIn(
@Param("resourceType") ResourceType resourceType, @Param("resourceIds") Collection<Long> resourceIds);

@Query(value = "select i_urr.* from iam_user_resource_role i_urr inner join iam_resource_role i_rr on i_urr.resource_role_id = i_rr.id "
+ "where i_rr.resource_type = :#{#resourceType.name()} and i_rr.role_name = :roleName and i_urr.resource_id = :resourceId",
nativeQuery = true)
List<UserResourceRoleEntity> findByResourceIdAndTypeAndName(@Param("resourceId") Long resourceId,
@Param("resourceType") ResourceType resourceType, @Param("roleName") String roleName);

@Query(value = "select i_urr.* from iam_user_resource_role i_urr inner join iam_resource_role i_rr on i_urr.resource_role_id = i_rr.id "
+ "where i_rr.resource_type = :#{#resourceType.name()} and i_urr.user_id = :userId",
nativeQuery = true)
List<UserResourceRoleEntity> findByUserIdAndResourceType(@Param("userId") Long userId,
@Param("resourceType") ResourceType resourceType);

default List<UserResourceRoleEntity> batchCreate(List<UserResourceRoleEntity> entities) {
String sql = InsertSqlTemplateBuilder.from("iam_user_resource_role")
.field(UserResourceRoleEntity_.userId)
.field(UserResourceRoleEntity_.resourceId)
.field(UserResourceRoleEntity_.resourceRoleId)
.field(UserResourceRoleEntity_.organizationId)
.build();
List<Function<UserResourceRoleEntity, Object>> getter = valueGetterBuilder()
.add(UserResourceRoleEntity::getUserId)
.add(UserResourceRoleEntity::getResourceId)
.add(UserResourceRoleEntity::getResourceRoleId)
.add(UserResourceRoleEntity::getOrganizationId)
.build();
return batchCreate(entities, sql, getter, UserResourceRoleEntity::setId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.oceanbase.odc.service.automation;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -29,6 +30,7 @@

import com.oceanbase.odc.common.lang.Pair;
import com.oceanbase.odc.core.authority.util.SkipAuthorize;
import com.oceanbase.odc.core.shared.constant.ResourceType;
import com.oceanbase.odc.service.automation.model.AutomationAction;
import com.oceanbase.odc.service.automation.model.AutomationCondition;
import com.oceanbase.odc.service.automation.model.AutomationRule;
Expand Down Expand Up @@ -127,15 +129,16 @@ protected void bindPermission(Long userId, AutomationAction action) {
protected void bindProjectRole(Long userId, AutomationAction action) {
Long projectId = ((Integer) action.getArguments().get("projectId")).longValue();
List<Integer> roleIds = (List<Integer>) action.getArguments().get("roles");
List<ProjectMember> members = resourceRoleService.listResourceRoles().stream()
.filter(resourceRole -> roleIds.contains(resourceRole.getId().intValue()))
.map(resourceRole -> {
ProjectMember member = new ProjectMember();
member.setRole(resourceRole.getRoleName());
member.setId(userId);
return member;
})
.collect(Collectors.toList());
List<ProjectMember> members =
resourceRoleService.listResourceRoles(Collections.singletonList(ResourceType.ODC_PROJECT)).stream()
.filter(resourceRole -> roleIds.contains(resourceRole.getId().intValue()))
.map(resourceRole -> {
ProjectMember member = new ProjectMember();
member.setRole(resourceRole.getRoleName());
member.setId(userId);
return member;
})
.collect(Collectors.toList());
projectService.createMembersSkipPermissionCheck(projectId, action.getOrganizationId(), members);
}

Expand Down
Loading
Loading