关于文件夹目录权限的一些思路

   需求为文件夹权限设置:管理员可以新建和维护文件夹(目录), 不同用户在拥有的目录的权限可控,权限分为只读、读写和管理。

   参考svn文件夹权限后想到两种实现方式:1.阻断式:A->B->C->D  当配置了D目录的权限为只读或者读写或者管理,那么只有用户访问D目录时才有权限,访问A或B或C都没有任何权限,仅仅在输入A->B->C->D完整目录时才有权限。这种配置起来比较繁琐。2.继承式:A->B->C->D  当配置了D目录的权限为只读或者读写或者管理,那么访问A或B或C目录都有“可读”的权限,即用户能分别访问A、B、C目录下的文件,但是不能写入或者删除。

    考虑到继承式的方式配置简单,所以采用此方式。

    以下为实现过程:

  1.文件夹权限表结构设计

CREATE TABLE `disk_file_folder_privilege` (
  `id` varchar(32) NOT NULL COMMENT '主键',
  `user_id` varchar(32) DEFAULT NULL COMMENT '用户id',
  `role_id` varchar(32) DEFAULT NULL,
  `present_catalog` varchar(32) DEFAULT NULL COMMENT '当前文件夹目录',
  `whole_catalog` varchar(512) DEFAULT NULL COMMENT '完整文件夹目录',
  `readable` char(1) DEFAULT NULL COMMENT '可读:1',
  `writable` char(1) DEFAULT NULL COMMENT '可写:1',
  `manage` char(1) DEFAULT NULL COMMENT '管理:1',
  `create_time` varchar(32) DEFAULT NULL,
  `update_time` varchar(32) DEFAULT NULL,
  `creater` varchar(32) DEFAULT NULL,
  `updater` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='文件夹权限表';

数据格式如下图:

2.保存文件夹权限接口服务

 /**
     * 保存文件夹目录权限
     *
     * @param diskFileFolderPrivilege
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult<Boolean> save(DiskFileFolderPrivilegeAO diskFileFolderPrivilege) {
        if (StringUtils.isEmpty(diskFileFolderPrivilege.getFileId())) {
            return ServiceResultHelper.genResultWithFaild("请选择文件夹目录", -1);
        }
        DiskFileAO diskFile = diskFileService.selectByPrimaryKey(diskFileFolderPrivilege.getFileId()).getData();
        if (diskFile == null) {
            return ServiceResultHelper.genResultWithFaild("文件或文件夹目录不存在", -1);
        }
        if (!StringUtils.isEmpty(diskFile.getTypecode())) {
            return ServiceResultHelper.genResultWithFaild("请选择文件夹目录", -1);
        }
        if (StringUtils.isEmpty(diskFileFolderPrivilege.getReadable())
                && StringUtils.isEmpty(diskFileFolderPrivilege.getWritable())
                && StringUtils.isEmpty(diskFileFolderPrivilege.getManage())) {
            return ServiceResultHelper.genResultWithFaild("请设置文件夹目录权限", -1);
        }
        List<DiskFileAO> fileFloderList = diskFileService.listAllFileFolder().getData();
        List<DiskFileAO> parentList = new ArrayList<>();
        UserAO user = AuthUtil.getCurrentUser();
        List<DiskFileFolderPrivilegeAO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fileFloderList)) {
            //查询所有父级
            diskFileService.getAllParentListWithChild(fileFloderList, diskFileFolderPrivilege.getFileId(), parentList);
            if (!CollectionUtils.isEmpty(parentList)) {
                for (int i = 0; i < parentList.size(); i++) {
                    DiskFileAO file = parentList.get(i);
                    DiskFileFolderPrivilegeAO tmp = new DiskFileFolderPrivilegeAO();
                    tmp.setUserId(diskFileFolderPrivilege.getUserId());
                    tmp.setRoleId(diskFileFolderPrivilege.getRoleId());
                    tmp.setCreater(user.getUserName());
                    tmp.setCreateTime(DateTimeUtil.formatDateTime(new Date()));
                    tmp.setPresentCatalog(file.getId());//当前文件夹目录
                    tmp.setReadable(Constant.VALID_FLG.toString());
                    //设置所选文件夹的可写,管理权限
                    if (i == parentList.size() - 1) {
                        if (Constant.VALID_FLG.toString().equals(diskFileFolderPrivilege.getWritable())) {
                            tmp.setWritable(diskFileFolderPrivilege.getWritable());
                        }
                        if (Constant.VALID_FLG.toString().equals(diskFileFolderPrivilege.getManage())) {
                            tmp.setWritable(Constant.VALID_FLG.toString());
                            tmp.setManage(diskFileFolderPrivilege.getManage());
                        }
                    }
                    if (i == 0) {
                        tmp.setWholeCatalog(file.getId());//完整文件夹目录
                    } else {
                        StringBuilder fileId = new StringBuilder();
                        for (int j = 0; j <= i; j++) {
                            fileId.append(parentList.get(j).getId());
                            if (j < i) {
                                fileId.append("/");
                            }
                        }
                        tmp.setWholeCatalog(fileId.toString());
                    }
                    result.add(tmp);
                }
            }
        }
        //子级目录不覆盖父级目录的权限,需要比较权限的大小
        deleteByFolderCatalog(result);
        if (!CollectionUtils.isEmpty(result)) {
            insertBatch(result);
        }
        return ServiceResultHelper.genResultWithSuccess();
    }


    /**
     * 删除已存在的权限,需要比较权限的大小
     * 子级目录不覆盖父级目录的权限
     *
     * @param result
     * @return
     */
    public ServiceResult deleteByFolderCatalog(List<DiskFileFolderPrivilegeAO> result) {
        if (!CollectionUtils.isEmpty(result)) {
            Iterator<DiskFileFolderPrivilegeAO> resultIt = result.iterator();
            while (resultIt.hasNext()) {
                DiskFileFolderPrivilegeAO privilege = resultIt.next();
                DiskFileFolderPrivilegeCriteria criteria = new DiskFileFolderPrivilegeCriteria();
                DiskFileFolderPrivilegeCriteria.Criteria c = criteria.createCriteria();
                String userId = privilege.getUserId();
                if (StringUtils.isEmpty(userId)) {
                    return ServiceResultHelper.genResultWithFaild("用户id不能为空", -1);
                }
                if (StringUtils.isEmpty(privilege.getWholeCatalog())) {
                    return ServiceResultHelper.genResultWithFaild("文件夹目录不能为空", -1);
                }
                if (!StringUtils.isEmpty(userId)) {
                    c.andUserIdEqualTo(userId);
                }
                c.andWholeCatalogEqualTo(privilege.getWholeCatalog());
                List<DiskFileFolderPrivilegeAO> privilegeList = selectByCriteria(criteria).getData();

                if (!CollectionUtils.isEmpty(privilegeList)) {
                    //如果权限已经存在了,并且权限的范围更大,则不再进行删除操作
                    boolean isRemove = false;//是否做移除操作
                    DiskFileFolderPrivilegeAO folderPrivilege = privilegeList.get(0);
                    //如果是最后一级目录,直接删除
                    if (!resultIt.hasNext()) {
                        deleteByCriteria(criteria);
                        isRemove = true;
                    } else {
                        if (!StringUtils.isEmpty(privilege.getManage())
                                && StringUtils.isEmpty(folderPrivilege.getManage())) {
                            deleteByCriteria(criteria);
                            isRemove = true;
                        } else if (!StringUtils.isEmpty(privilege.getWritable())
                                && StringUtils.isEmpty(folderPrivilege.getWritable())) {
                            deleteByCriteria(criteria);
                            isRemove = true;
                        }
                    }
                    if (!isRemove) {
                        resultIt.remove();
                    }
                }
            }
        }
        return ServiceResultHelper.genResultWithSuccess();
    }

    @Override
    public int insertBatch(List<DiskFileFolderPrivilegeAO> privilegeAOList) {
        return diskFileFolderPrivilegeCustomizedMapper.insertBatch(privilegeAOList);
    }

mybatis中的xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<!--

    Description: A generated data access implementation of entity DiskFileFolderPrivilege.
                 Generated at 2020-07-31 11:23:44, do NOT modify!
    Author: <a href="mailto:DL88250@gmail.com">Liang Ding</a>
    Version: 1.0.0.0, Jul 31, 2020

-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.datainvest.dms.system.dao.customized.DiskFileFolderPrivilegeCustomizedMapper" >
  <resultMap id="BaseResultMap" type="cn.datainvest.dms.system.entity.customized.DiskFileFolderPrivilegeAO" >
    <id column="id" property="id" jdbcType="VARCHAR" />
    <result column="user_id" property="userId" jdbcType="VARCHAR" />
    <result column="role_id" property="roleId" jdbcType="VARCHAR" />
    <result column="present_catalog" property="presentCatalog" jdbcType="VARCHAR" />
    <result column="whole_catalog" property="wholeCatalog" jdbcType="VARCHAR" />
    <result column="readable" property="readable" jdbcType="CHAR" />
    <result column="writable" property="writable" jdbcType="CHAR" />
    <result column="manage" property="manage" jdbcType="CHAR" />
    <result column="create_time" property="createTime" jdbcType="VARCHAR" />
    <result column="update_time" property="updateTime" jdbcType="VARCHAR" />
    <result column="creater" property="creater" jdbcType="VARCHAR" />
    <result column="updater" property="updater" jdbcType="VARCHAR" />
  </resultMap>

  <!-- 批量插入 -->
  <insert id="insertBatch" parameterType="java.util.List">
    insert into disk_file_folder_privilege (id, user_id, role_id,
    present_catalog, whole_catalog, readable, writable,
    manage, create_time, update_time,
    creater, updater)
    values
    <foreach collection="list" item="item" index="index" separator=",">
      (uuid_short(), #{item.userId,jdbcType=VARCHAR}, #{item.roleId,jdbcType=VARCHAR},
      #{item.presentCatalog,jdbcType=VARCHAR}, #{item.wholeCatalog,jdbcType=VARCHAR}, #{item.readable,jdbcType=CHAR}, #{item.writable,jdbcType=CHAR},
      #{item.manage,jdbcType=CHAR}, #{item.createTime,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=VARCHAR},
      #{item.creater,jdbcType=VARCHAR}, #{item.updater,jdbcType=VARCHAR})
    </foreach>
  </insert>
</mapper>

 pojo,配置:

import java.io.Serializable;
import cn.datainvest.dms.system.entity.gen.DiskFileFolderPrivilege;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;

/**
 * 应用对象 - DiskFileFolderPrivilege.
 * <p>
 * 该类于 2020-07-31 10:46:58 首次生成,后由开发手工维护。
 * </p>
 * @author yangfeng
 * @version 1.0.0, Jul 31, 2020
 */
@JsonSerialize(include = Inclusion.ALWAYS)
public final class DiskFileFolderPrivilegeAO extends DiskFileFolderPrivilege implements Serializable {

    /**
     * 默认的序列化 id.
     */
    private static final long serialVersionUID = 1L;

    private String fileId;

    public String getFileId() {
        return fileId;
    }

    public void setFileId(String fileId) {
        this.fileId = fileId;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }
}

    fileId用来接收配置的文件夹id, readable、 writable、 manage三个字段分别对应可读、可写、管理权限。值为1是表示有相应权限没有则不需要传入值,保持null。

      presentCatalog字段表示当前文件夹id,wholeCatalog表示完整目录的文件夹id。为什么不存文件名:考虑到文件夹目录会重命名导致权限失效。

     wholeCatalog拆分的各级父目录readable均为1,均有可读权限。删除已存在的权限,需要比较权限的大小 ,子级目录不覆盖父级目录的权限。 拆分目录后如果是最后一级目录(即选择的当前文件夹),直接删除对应的权限,重新设置。否则,对应的其他上级目录,如果权限已经存在了,并且权限的范围更大,则不再进行删除操作,防止缩小父级权限。
      3. 文件表:

CREATE TABLE `disk_file` (
  `id` varchar(50) NOT NULL,
  `createtime` datetime DEFAULT NULL,
  `createuserid` varchar(50) DEFAULT NULL,
  `createusername` varchar(50) DEFAULT NULL,
  `filemd5` varchar(200) DEFAULT NULL,
  `filename` varchar(255) DEFAULT NULL,
  `filesize` bigint(20) NOT NULL,
  `filesuffix` varchar(20) DEFAULT NULL,
  `filetype` int(11) DEFAULT NULL,
  `imgsize` varchar(50) DEFAULT NULL,
  `pid` varchar(50) DEFAULT NULL,
  `thumbnailurl` varchar(200) DEFAULT NULL,
  `typecode` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UKfjg8ov86e52cc1vw2g4cahpu7` (`createuserid`,`pid`,`filetype`,`filename`),
  KEY `IDX7h8ca5qp48qow851woryvg8q` (`pid`),
  KEY `IDX9j6hnchh4o79nofxhjgy0lc29` (`filename`),
  KEY `IDXlhtq88mi2kvwxihin21rvvm9b` (`typecode`),
  KEY `IDXb244b04v1wu3ftqfqjt7wodks` (`filesuffix`),
  KEY `IDXq0mhp53s6a40gh5w93bqmx5jp` (`filetype`),
  KEY `IDXc7snngp84h66d6f64u0l0hb56` (`createuserid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

type_code为空表示文件夹目录。pid=“0”,表示根目录。查询可读的文件和文件夹,关联文件夹目录权限,超级管理员可以查看所有。普通用户可以查看拥有权限的文件夹,以及创建者是本人的文件和文件夹。

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.datainvest.dms.system.dao.customized.DiskFileCustomizedMapper" >
  <resultMap id="CustomResultMap" type="cn.datainvest.dms.system.entity.customized.DiskFileAO" >
    <id column="id" property="id" jdbcType="VARCHAR" />
    <result column="createtime" property="createtime" jdbcType="TIMESTAMP" />
    <result column="createuserid" property="createuserid" jdbcType="VARCHAR" />
    <result column="createusername" property="createusername" jdbcType="VARCHAR" />
    <result column="filemd5" property="filemd5" jdbcType="VARCHAR" />
    <result column="filename" property="filename" jdbcType="VARCHAR" />
    <result column="filesize" property="filesize" jdbcType="BIGINT" />
    <result column="filesuffix" property="filesuffix" jdbcType="VARCHAR" />
    <result column="filetype" property="filetype" jdbcType="INTEGER" />
    <result column="imgsize" property="imgsize" jdbcType="VARCHAR" />
    <result column="pid" property="pid" jdbcType="VARCHAR" />
    <result column="fileicon" property="fileicon" jdbcType="VARCHAR" />
    <result column="thumbnailurl" property="thumbnailurl" jdbcType="VARCHAR" />
    <result column="typecode" property="typecode" jdbcType="VARCHAR" />
  </resultMap>

  <select id="findAllList"  resultMap="CustomResultMap"
          parameterType="cn.datainvest.dms.system.dto.request.DiskFileRequest">
      SELECT
              t2.id,
              t2.filename,
              t2.filesize,
              t2.filetype,
              t2.filemd5,
              t2.filesuffix,
              date_format(t2.createtime,'%Y-%m-%d %H:%i:%S') AS createtime,
              dts.icon AS fileicon
      FROM
      (
          SELECT
                *
          FROM
                disk_file t1
          <if test="isSuperAdmin != null and isSuperAdmin != '' and isSuperAdmin == 'false' ">
          WHERE
                createuserid = #{userid, jdbcType=VARCHAR}
                AND pid = #{pid, jdbcType=VARCHAR}
          UNION
          SELECT
                df.*
          FROM
                disk_file df
          INNER JOIN (
                  SELECT
                        present_catalog
                  FROM
                        `disk_file_folder_privilege`
                  WHERE
                        user_id = #{userid, jdbcType=VARCHAR}
          ) tmp ON (tmp.present_catalog = df.id OR tmp.present_catalog = df.pid)
          </if>
          WHERE
                pid = #{pid, jdbcType=VARCHAR}
      ) t2
      LEFT JOIN
              disk_type_suffix dts
              ON dts.suffix = t2.filesuffix
              AND dts.typecode = t2.typecode
    <where>
        <if test="typecode != null and typecode != '' and typecode != 'all' and typecode != 'ALL' ">
            AND t2.typecode = #{typecode, jdbcType=VARCHAR}
        </if>
        <if test="filesuffix != null and filesuffix != '' ">
            AND t2.filesuffix = #{filesuffix, jdbcType=VARCHAR}
        </if>
        <if test="filename != null and filename != ''">
            AND t2.filename LIKE CONCAT('%', #{filename, jdbcType=VARCHAR},'%')
        </if>
    </where>
    <choose>
        <when test="orderfield != null and orderfield != '' and ordertype != null and ordertype != ''">
          order by ${orderfield} ${ordertype}
        </when>
        <otherwise>
          order by t2.createtime desc
        </otherwise>
    </choose>
  </select>

 

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页