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

[#2705] feat(core): Add the relational backend for User Entity #2850

Merged
merged 24 commits into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from 22 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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.slf4j.LoggerFactory;

/* The utilization class of authorization module*/
class AuthorizationUtils {
public class AuthorizationUtils {

static final String USER_DOES_NOT_EXIST_MSG = "User %s does not exist in th metalake %s";
static final String GROUP_DOES_NOT_EXIST_MSG = "Group %s does not exist in th metalake %s";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@
import com.datastrato.gravitino.meta.BaseMetalake;
import com.datastrato.gravitino.meta.CatalogEntity;
import com.datastrato.gravitino.meta.FilesetEntity;
import com.datastrato.gravitino.meta.RoleEntity;
import com.datastrato.gravitino.meta.SchemaEntity;
import com.datastrato.gravitino.meta.TableEntity;
import com.datastrato.gravitino.meta.TopicEntity;
import com.datastrato.gravitino.meta.UserEntity;
import com.datastrato.gravitino.storage.relational.converters.SQLExceptionConverterFactory;
import com.datastrato.gravitino.storage.relational.service.CatalogMetaService;
import com.datastrato.gravitino.storage.relational.service.FilesetMetaService;
import com.datastrato.gravitino.storage.relational.service.MetalakeMetaService;
import com.datastrato.gravitino.storage.relational.service.RoleMetaService;
import com.datastrato.gravitino.storage.relational.service.SchemaMetaService;
import com.datastrato.gravitino.storage.relational.service.TableMetaService;
import com.datastrato.gravitino.storage.relational.service.TopicMetaService;
import com.datastrato.gravitino.storage.relational.service.UserMetaService;
import com.datastrato.gravitino.storage.relational.session.SqlSessionFactoryHelper;
import java.io.IOException;
import java.util.List;
Expand Down Expand Up @@ -95,6 +99,10 @@ public <E extends Entity & HasIdentifier> void insert(E e, boolean overwritten)
FilesetMetaService.getInstance().insertFileset((FilesetEntity) e, overwritten);
} else if (e instanceof TopicEntity) {
TopicMetaService.getInstance().insertTopic((TopicEntity) e, overwritten);
} else if (e instanceof UserEntity) {
UserMetaService.getInstance().insertUser((UserEntity) e, overwritten);
} else if (e instanceof RoleEntity) {
RoleMetaService.getInstance().insertRole((RoleEntity) e, overwritten);
} else {
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for insert operation", e.getClass());
Expand All @@ -118,6 +126,8 @@ public <E extends Entity & HasIdentifier> E update(
return (E) FilesetMetaService.getInstance().updateFileset(ident, updater);
case TOPIC:
return (E) TopicMetaService.getInstance().updateTopic(ident, updater);
case USER:
return (E) UserMetaService.getInstance().updateUser(ident, updater);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for update operation", entityType);
Expand All @@ -140,6 +150,8 @@ public <E extends Entity & HasIdentifier> E get(
return (E) FilesetMetaService.getInstance().getFilesetByIdentifier(ident);
case TOPIC:
return (E) TopicMetaService.getInstance().getTopicByIdentifier(ident);
case USER:
return (E) UserMetaService.getInstance().getUserByIdentifier(ident);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for get operation", entityType);
Expand All @@ -161,6 +173,8 @@ public boolean delete(NameIdentifier ident, Entity.EntityType entityType, boolea
return FilesetMetaService.getInstance().deleteFileset(ident);
case TOPIC:
return TopicMetaService.getInstance().deleteTopic(ident);
case USER:
return UserMetaService.getInstance().deleteUser(ident);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for delete operation", entityType);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/

package com.datastrato.gravitino.storage.relational.mapper;

import com.datastrato.gravitino.storage.relational.po.RolePO;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
* A MyBatis Mapper for table meta operation SQLs.
*
* <p>This interface class is a specification defined by MyBatis. It requires this interface class
* to identify the corresponding SQLs for execution. We can write SQLs in an additional XML file, or
* write SQLs with annotations in this interface Mapper. See: <a
* href="https://mybatis.org/mybatis-3/getting-started.html"></a>
*/
public interface RoleMetaMapper {
String ROLE_TABLE_NAME = "role_meta";
String RELATION_TABLE_NAME = "user_role_rel";

@Select(
"SELECT role_id as roleId FROM "
+ ROLE_TABLE_NAME
+ " WHERE metalake_id = #{metalakeId} AND role_name = #{roleName}"
+ " AND deleted_at = 0")
Long selectRoleIdByMetalakeIdAndName(
@Param("metalakeId") Long metalakeId, @Param("roleName") String name);

@Select(
"SELECT ro.role_id as roleId, ro.role_name as roleName,"
+ " ro.metalake_id as metalakeId, ro.properties as properties,"
+ " ro.securable_object as securableObject, ro.privileges as privileges,"
+ " ro.audit_info as auditInfo, ro.current_version as currentVersion,"
+ " ro.last_version as lastVersion, ro.deleted_at as deletedAt"
+ " FROM "
+ ROLE_TABLE_NAME
+ " ro JOIN "
+ RELATION_TABLE_NAME
+ " re ON ro.role_id = re.role_id"
+ " WHERE re.user_id = #{userId}"
+ " AND ro.deleted_at = 0 AND re.deleted_at = 0")
List<RolePO> listRolesByUserId(@Param("userId") Long userId);

@Insert(
"INSERT INTO "
+ ROLE_TABLE_NAME
+ "(role_id, role_name,"
+ " metalake_id, properties,"
+ " securable_object, privileges,"
+ " audit_info, current_version, last_version, deleted_at)"
+ " VALUES("
+ " #{roleMeta.roleId},"
+ " #{roleMeta.roleName},"
+ " #{roleMeta.metalakeId},"
+ " #{roleMeta.properties},"
+ " #{roleMeta.securableObject},"
+ " #{roleMeta.privileges},"
+ " #{roleMeta.auditInfo},"
+ " #{roleMeta.currentVersion},"
+ " #{roleMeta.lastVersion},"
+ " #{roleMeta.deletedAt}"
+ " )")
void insertRoleMeta(@Param("roleMeta") RolePO rolePO);

@Insert(
"INSERT INTO "
+ ROLE_TABLE_NAME
+ "(role_id, role_name,"
+ " metalake_id, properties,"
+ " securable_object, privileges,"
+ " audit_info, current_version, last_version, deleted_at)"
+ " VALUES("
+ " #{roleMeta.roleId},"
+ " #{roleMeta.roleName},"
+ " #{roleMeta.metalakeId},"
+ " #{roleMeta.properties},"
+ " #{roleMeta.securableObject},"
+ " #{roleMeta.privileges},"
+ " #{roleMeta.auditInfo},"
+ " #{roleMeta.currentVersion},"
+ " #{roleMeta.lastVersion},"
+ " #{roleMeta.deletedAt}"
+ " ) ON DUPLICATE KEY UPDATE"
+ " role_name = #{roleMeta.roleName},"
+ " metalake_id = #{roleMeta.metalakeId},"
+ " properties = #{roleMeta.properties},"
+ " securable_object = #{roleMeta.securableObject},"
+ " privileges = #{roleMeta.privileges},"
+ " audit_info = #{roleMeta.auditInfo},"
+ " current_version = #{roleMeta.currentVersion},"
+ " last_version = #{roleMeta.lastVersion},"
+ " deleted_at = #{roleMeta.deletedAt}")
void insertRoleMetaOnDuplicateKeyUpdate(@Param("roleMeta") RolePO rolePO);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/

package com.datastrato.gravitino.storage.relational.mapper;

import com.datastrato.gravitino.storage.relational.po.UserPO;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

/**
* A MyBatis Mapper for table meta operation SQLs.
*
* <p>This interface class is a specification defined by MyBatis. It requires this interface class
* to identify the corresponding SQLs for execution. We can write SQLs in an additional XML file, or
* write SQLs with annotations in this interface Mapper. See: <a
* href="https://mybatis.org/mybatis-3/getting-started.html"></a>
*/
public interface UserMetaMapper {
String TABLE_NAME = "user_meta";

@Select(
"SELECT user_id as userId FROM "
+ TABLE_NAME
+ " WHERE metalake_id = #{metalakeId} AND user_name = #{userName}"
+ " AND deleted_at = 0")
Long selectUserIdByMetalakeIdAndName(
@Param("metalakeId") Long metalakeId, @Param("userName") String name);

@Select(
"SELECT user_id as userId, user_name as userName,"
+ " metalake_id as metalakeId,"
+ " audit_info as auditInfo,"
+ " current_version as currentVersion, last_version as lastVersion,"
+ " deleted_at as deletedAt"
+ " FROM "
+ TABLE_NAME
+ " WHERE metalake_id = #{metalakeId} AND user_name = #{userName}"
+ " AND deleted_at = 0")
UserPO selectUserMetaByMetalakeIdAndName(
@Param("metalakeId") Long metalakeId, @Param("userName") String name);

@Insert(
"INSERT INTO "
+ TABLE_NAME
+ "(user_id, user_name,"
+ " metalake_id, audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES("
+ " #{userMeta.userId},"
+ " #{userMeta.userName},"
+ " #{userMeta.metalakeId},"
+ " #{userMeta.auditInfo},"
+ " #{userMeta.currentVersion},"
+ " #{userMeta.lastVersion},"
+ " #{userMeta.deletedAt}"
+ " )")
void insertUserMeta(@Param("userMeta") UserPO userPO);

@Insert(
"INSERT INTO "
+ TABLE_NAME
+ "(user_id, user_name,"
+ "metalake_id, audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES("
+ " #{userMeta.userId},"
+ " #{userMeta.userName},"
+ " #{userMeta.metalakeId},"
+ " #{userMeta.auditInfo},"
+ " #{userMeta.currentVersion},"
+ " #{userMeta.lastVersion},"
+ " #{userMeta.deletedAt}"
+ " )"
+ " ON DUPLICATE KEY UPDATE"
+ " user_name = #{userMeta.userName},"
+ " metalake_id = #{userMeta.metalakeId},"
+ " audit_info = #{userMeta.auditInfo},"
+ " current_version = #{userMeta.currentVersion},"
+ " last_version = #{userMeta.lastVersion},"
+ " deleted_at = #{userMeta.deletedAt}")
void insertUserMetaOnDuplicateKeyUpdate(@Param("userMeta") UserPO userPO);

@Update(
"UPDATE "
+ TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE user_id = #{userId} AND deleted_at = 0")
void softDeleteUserMetaByUserId(@Param("userId") Long userId);

@Update(
"UPDATE "
+ TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE metalake_id = #{metalakeId} AND deleted_at = 0")
void softDeleteUserMetasByMetalakeId(@Param("metalakeId") Long metalakeId);

@Update(
"UPDATE "
+ TABLE_NAME
+ " SET user_name = #{newUserMeta.userName},"
+ " metalake_id = #{newUserMeta.metalakeId},"
+ " audit_info = #{newUserMeta.auditInfo},"
+ " current_version = #{newUserMeta.currentVersion},"
+ " last_version = #{newUserMeta.lastVersion},"
+ " deleted_at = #{newUserMeta.deletedAt}"
+ " WHERE user_id = #{oldUserMeta.userId}"
+ " AND user_name = #{oldUserMeta.userName}"
+ " AND metalake_id = #{oldUserMeta.metalakeId}"
+ " AND audit_info = #{oldUserMeta.auditInfo}"
+ " AND current_version = #{oldUserMeta.currentVersion}"
+ " AND last_version = #{oldUserMeta.lastVersion}"
+ " AND deleted_at = 0")
Integer updateUserMeta(
@Param("newUserMeta") UserPO newUserPO, @Param("oldUserMeta") UserPO oldUserPO);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/

package com.datastrato.gravitino.storage.relational.mapper;

import com.datastrato.gravitino.storage.relational.po.UserRoleRelPO;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

/**
* A MyBatis Mapper for table meta operation SQLs.
*
* <p>This interface class is a specification defined by MyBatis. It requires this interface class
* to identify the corresponding SQLs for execution. We can write SQLs in an additional XML file, or
* write SQLs with annotations in this interface Mapper. See: <a
* href="https://mybatis.org/mybatis-3/getting-started.html"></a>
*/
public interface UserRoleRelMapper {
String RELATION_TABLE_NAME = "user_role_rel";
String USER_TABLE_NAME = "user_meta";

@Insert({
"<script>",
"INSERT INTO "
+ RELATION_TABLE_NAME
+ "(user_id, role_id,"
+ " audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES ",
"<foreach collection='userRoleRels' item='item' separator=','>",
"(#{item.userId},"
+ " #{item.roleId},"
+ " #{item.auditInfo},"
+ " #{item.currentVersion},"
+ " #{item.lastVersion},"
+ " #{item.deletedAt})",
"</foreach>",
"</script>"
})
void batchInsertUserRoleRel(@Param("userRoleRels") List<UserRoleRelPO> userRoleRelPOs);

@Insert({
"<script>",
"INSERT INTO "
+ RELATION_TABLE_NAME
+ "(user_id, role_id,"
+ " audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES ",
"<foreach collection='userRoleRels' item='item' separator=','>",
"(#{item.userId},"
+ " #{item.roleId},"
+ " #{item.auditInfo},"
+ " #{item.currentVersion},"
+ " #{item.lastVersion},"
+ " #{item.deletedAt})",
"</foreach>",
" ON DUPLICATE KEY UPDATE"
+ " user_id = VALUES(user_id),"
+ " role_id = VALUES(role_id),"
+ " audit_info = VALUES(audit_info),"
+ " current_version = VALUES(current_version),"
+ " last_version = VALUES(last_version),"
+ " deleted_at = VALUES(deleted_at)",
"</script>"
})
void batchInsertUserRoleRelOnDuplicateKeyUpdate(
@Param("userRoleRels") List<UserRoleRelPO> userRoleRelPOs);

@Update(
"UPDATE "
+ RELATION_TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE user_id = #{userId} AND deleted_at = 0")
void softDeleteUserRoleRelByUserId(@Param("userId") Long userId);

@Update({
"<script>",
"UPDATE "
+ RELATION_TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE user_id = #{userId} AND role_id in (",
"<foreach collection='roleIds' item='roleId' separator=','>",
"#{roleId}",
"</foreach>",
") " + "AND deleted_at = 0",
"</script>"
})
void softDeleteUserRoleRelByUserAndRoles(
@Param("userId") Long userId, @Param("roleIds") List<Long> roleIds);

@Update(
"UPDATE "
+ RELATION_TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE user_id IN (SELECT user_id FROM "
+ USER_TABLE_NAME
+ " WHERE metalake_id = #{metalakeId} AND deleted_at = 0)"
+ " AND deleted_at = 0")
void softDeleteUserRoleRelByMetalakeId(Long metalakeId);
}
Loading
Loading