库函数增加修改日志记录,增加函数修改授权,展示优化
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
package com.zyplayer.doc.data.repository.manage.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据库函数修改日志
|
||||
* </p>
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2021-04-26
|
||||
*/
|
||||
public class DbProcLog implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键自增ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 数据源ID
|
||||
*/
|
||||
private Long datasourceId;
|
||||
|
||||
/**
|
||||
* 所属数据库
|
||||
*/
|
||||
private String procDb;
|
||||
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String procName;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private String procType;
|
||||
|
||||
/**
|
||||
* 函数创建SQL
|
||||
*/
|
||||
private String procBody;
|
||||
|
||||
/**
|
||||
* 保存状态 1=成功 2=失败
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建人ID
|
||||
*/
|
||||
private Long createUserId;
|
||||
|
||||
/**
|
||||
* 创建人名字
|
||||
*/
|
||||
private String createUserName;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public Long getDatasourceId() {
|
||||
return datasourceId;
|
||||
}
|
||||
|
||||
public void setDatasourceId(Long datasourceId) {
|
||||
this.datasourceId = datasourceId;
|
||||
}
|
||||
public String getProcDb() {
|
||||
return procDb;
|
||||
}
|
||||
|
||||
public void setProcDb(String procDb) {
|
||||
this.procDb = procDb;
|
||||
}
|
||||
public String getProcName() {
|
||||
return procName;
|
||||
}
|
||||
|
||||
public void setProcName(String procName) {
|
||||
this.procName = procName;
|
||||
}
|
||||
public String getProcType() {
|
||||
return procType;
|
||||
}
|
||||
|
||||
public void setProcType(String procType) {
|
||||
this.procType = procType;
|
||||
}
|
||||
public String getProcBody() {
|
||||
return procBody;
|
||||
}
|
||||
|
||||
public void setProcBody(String procBody) {
|
||||
this.procBody = procBody;
|
||||
}
|
||||
public Long getCreateUserId() {
|
||||
return createUserId;
|
||||
}
|
||||
|
||||
public void setCreateUserId(Long createUserId) {
|
||||
this.createUserId = createUserId;
|
||||
}
|
||||
public String getCreateUserName() {
|
||||
return createUserName;
|
||||
}
|
||||
|
||||
public void setCreateUserName(String createUserName) {
|
||||
this.createUserName = createUserName;
|
||||
}
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DbProcLog{" +
|
||||
"id=" + id +
|
||||
", datasourceId=" + datasourceId +
|
||||
", procDb=" + procDb +
|
||||
", procName=" + procName +
|
||||
", procType=" + procType +
|
||||
", procBody=" + procBody +
|
||||
", createUserId=" + createUserId +
|
||||
", createUserName=" + createUserName +
|
||||
", createTime=" + createTime +
|
||||
"}";
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.zyplayer.doc.data.repository.manage.mapper;
|
||||
|
||||
import com.zyplayer.doc.data.repository.manage.entity.DbProcLog;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据库函数修改日志 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2021-04-26
|
||||
*/
|
||||
public interface DbProcLogMapper extends BaseMapper<DbProcLog> {
|
||||
|
||||
}
|
||||
@@ -13,15 +13,15 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CodeGenerator {
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
final String moduleName = "manage";
|
||||
// final String[] tableName = { "zyplayer_storage", "auth_info", "user_auth", "user_info", "db_datasource" };
|
||||
// final String[] tableName = { "wiki_space", "wiki_page", "wiki_page_content", "wiki_page_file", "wiki_page_comment", "wiki_page_zan" };
|
||||
// final String[] tableName = { "db_datasource", "es_datasource", "db_favorite" };
|
||||
final String[] tableName = { "wiki_space_favorite", "user_setting" };
|
||||
|
||||
final String[] tableName = {"db_proc_log"};
|
||||
|
||||
// 代码生成器
|
||||
AutoGenerator mpg = new AutoGenerator();
|
||||
// 全局配置
|
||||
@@ -35,7 +35,7 @@ public class CodeGenerator {
|
||||
gc.setServiceName("%sService");
|
||||
gc.setControllerName("Generator%sController");
|
||||
mpg.setGlobalConfig(gc);
|
||||
|
||||
|
||||
// 数据源配置
|
||||
DataSourceConfig dsc = new DataSourceConfig();
|
||||
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/zyplayer_doc_manage?useUnicode=true&useSSL=false&characterEncoding=utf8");
|
||||
@@ -44,7 +44,7 @@ public class CodeGenerator {
|
||||
dsc.setUsername("root");
|
||||
dsc.setPassword("root");
|
||||
mpg.setDataSource(dsc);
|
||||
|
||||
|
||||
// 包配置
|
||||
final PackageConfig pc = new PackageConfig();
|
||||
pc.setModuleName(null);
|
||||
@@ -55,7 +55,7 @@ public class CodeGenerator {
|
||||
pc.setService("service.manage");
|
||||
pc.setServiceImpl("service.manage.impl");
|
||||
mpg.setPackageInfo(pc);
|
||||
|
||||
|
||||
// 自定义配置
|
||||
InjectionConfig cfg = new InjectionConfig() {
|
||||
@Override
|
||||
@@ -73,7 +73,7 @@ public class CodeGenerator {
|
||||
cfg.setFileOutConfigList(focList);
|
||||
mpg.setCfg(cfg);
|
||||
mpg.setTemplate(new TemplateConfig().setXml(null));
|
||||
|
||||
|
||||
// 策略配置
|
||||
StrategyConfig strategy = new StrategyConfig();
|
||||
strategy.setNaming(NamingStrategy.underline_to_camel);
|
||||
@@ -90,5 +90,5 @@ public class CodeGenerator {
|
||||
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
|
||||
mpg.execute();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.zyplayer.doc.data.service.manage;
|
||||
|
||||
import com.zyplayer.doc.data.repository.manage.entity.DbProcLog;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据库函数修改日志 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2021-04-26
|
||||
*/
|
||||
public interface DbProcLogService extends IService<DbProcLog> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.zyplayer.doc.data.service.manage.impl;
|
||||
|
||||
import com.zyplayer.doc.data.repository.manage.entity.DbProcLog;
|
||||
import com.zyplayer.doc.data.repository.manage.mapper.DbProcLogMapper;
|
||||
import com.zyplayer.doc.data.service.manage.DbProcLogService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据库函数修改日志 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2021-04-26
|
||||
*/
|
||||
@Service
|
||||
public class DbProcLogServiceImpl extends ServiceImpl<DbProcLogMapper, DbProcLog> implements DbProcLogService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.zyplayer.doc.data.repository.manage.mapper.DbProcLogMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -67,6 +67,11 @@
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>2.1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.47</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -91,6 +91,11 @@ public class DbDataSourceAuthController {
|
||||
UserAuth userAuth = this.createUserAuth(sourceId, currentUser.getUserId(), authVo.getUserId(), authId);
|
||||
userAuthList.add(userAuth);
|
||||
}
|
||||
if (Objects.equals(authVo.getProcEditAuth(), 1)) {
|
||||
Long authId = authInfoMap.get(DbAuthType.PROC_EDIT.getName());
|
||||
UserAuth userAuth = this.createUserAuth(sourceId, currentUser.getUserId(), authVo.getUserId(), authId);
|
||||
userAuthList.add(userAuth);
|
||||
}
|
||||
if (userAuthList.size() <= 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -121,7 +126,6 @@ public class DbDataSourceAuthController {
|
||||
userAuthGroup.forEach((key, value) -> {
|
||||
Set<String> authNameSet = value.stream().map(auth -> authInfoMap.get(auth.getAuthId())).collect(Collectors.toSet());
|
||||
UserDbAuthVo authVo = new UserDbAuthVo();
|
||||
authVo.setExecuteAuth(0);
|
||||
if (this.haveAuth(authNameSet, DbAuthType.UPDATE) == 1) {
|
||||
authVo.setExecuteAuth(3);
|
||||
} else if (this.haveAuth(authNameSet, DbAuthType.SELECT) == 1) {
|
||||
@@ -130,6 +134,7 @@ public class DbDataSourceAuthController {
|
||||
authVo.setExecuteAuth(1);
|
||||
}
|
||||
authVo.setDescEditAuth(this.haveAuth(authNameSet, DbAuthType.DESC_EDIT));
|
||||
authVo.setProcEditAuth(this.haveAuth(authNameSet, DbAuthType.PROC_EDIT));
|
||||
authVo.setUserId(key);
|
||||
authVo.setUserName(userInfoMap.get(key));
|
||||
authVoList.add(authVo);
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.zyplayer.doc.db.framework.configuration.DatasourceUtil;
|
||||
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
|
||||
import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
|
||||
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -59,8 +60,13 @@ public class DbDatasourceController {
|
||||
public ResponseJson groups() {
|
||||
QueryWrapper<DbDatasource> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("yn", 1);
|
||||
wrapper.isNotNull("group_name");
|
||||
wrapper.select("group_name");
|
||||
wrapper.groupBy("group_name");
|
||||
List<DbDatasource> datasourceList = dbDatasourceService.list(wrapper);
|
||||
if (CollectionUtils.isEmpty(datasourceList)) {
|
||||
return DocDbResponseJson.ok();
|
||||
}
|
||||
Set<String> groupNameSet = datasourceList.stream().map(DbDatasource::getGroupName).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
|
||||
return DocDbResponseJson.ok(groupNameSet);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
package com.zyplayer.doc.db.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException;
|
||||
import com.zyplayer.doc.core.annotation.AuthMan;
|
||||
import com.zyplayer.doc.core.exception.ConfirmException;
|
||||
import com.zyplayer.doc.core.json.ResponseJson;
|
||||
import com.zyplayer.doc.data.config.security.DocUserDetails;
|
||||
import com.zyplayer.doc.data.config.security.DocUserUtil;
|
||||
import com.zyplayer.doc.data.repository.manage.entity.DbDatasource;
|
||||
import com.zyplayer.doc.data.repository.manage.entity.DbProcLog;
|
||||
import com.zyplayer.doc.data.repository.support.consts.DocAuthConst;
|
||||
import com.zyplayer.doc.data.service.manage.DbProcLogService;
|
||||
import com.zyplayer.doc.db.controller.param.ProcedureListParam;
|
||||
import com.zyplayer.doc.db.framework.consts.DbAuthType;
|
||||
import com.zyplayer.doc.db.framework.db.dto.ProcedureDto;
|
||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteResult;
|
||||
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
|
||||
@@ -18,6 +28,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -34,6 +45,8 @@ public class DbProcedureController {
|
||||
|
||||
@Resource
|
||||
DbBaseFactory dbBaseFactory;
|
||||
@Resource
|
||||
DbProcLogService dbProcLogService;
|
||||
|
||||
/**
|
||||
* 存储过程列表
|
||||
@@ -43,18 +56,19 @@ public class DbProcedureController {
|
||||
*/
|
||||
@PostMapping(value = "/list")
|
||||
public ResponseJson list(ProcedureListParam procedureParam) {
|
||||
boolean manageAuth = DocUserUtil.haveAuth(DocAuthConst.DB_DATASOURCE_MANAGE);
|
||||
if (!manageAuth) {
|
||||
return DocDbResponseJson.warn("没有该数据源的管理权限");
|
||||
try {
|
||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(procedureParam.getSourceId());
|
||||
procedureParam.setOffset((procedureParam.getPageNum() - 1) * procedureParam.getPageSize());
|
||||
List<ProcedureDto> procedureDtoList = dbBaseService.getProcedureList(procedureParam);
|
||||
DocDbResponseJson responseJson = DocDbResponseJson.ok(procedureDtoList);
|
||||
if (procedureParam.getPageNum() == 1) {
|
||||
responseJson.setTotal(dbBaseService.getProcedureCount(procedureParam));
|
||||
}
|
||||
return responseJson;
|
||||
} catch (Exception e) {
|
||||
// 一般是数据库的帐号没权限查存储过程
|
||||
return DocDbResponseJson.error(e.getMessage());
|
||||
}
|
||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(procedureParam.getSourceId());
|
||||
procedureParam.setOffset((procedureParam.getPageNum() - 1) * procedureParam.getPageSize());
|
||||
List<ProcedureDto> procedureDtoList = dbBaseService.getProcedureList(procedureParam);
|
||||
DocDbResponseJson responseJson = DocDbResponseJson.ok(procedureDtoList);
|
||||
if (procedureParam.getPageNum() == 1) {
|
||||
responseJson.setTotal(dbBaseService.getProcedureCount(procedureParam));
|
||||
}
|
||||
return responseJson;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,13 +82,14 @@ public class DbProcedureController {
|
||||
*/
|
||||
@PostMapping(value = "/detail")
|
||||
public ResponseJson detail(Long sourceId, String dbName, String typeName, String procName) {
|
||||
boolean manageAuth = DocUserUtil.haveAuth(DocAuthConst.DB_DATASOURCE_MANAGE);
|
||||
if (!manageAuth) {
|
||||
return DocDbResponseJson.warn("没有该数据源的管理权限");
|
||||
}
|
||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(sourceId);
|
||||
ProcedureDto procedureDto = dbBaseService.getProcedureDetail(sourceId, dbName, typeName, procName);
|
||||
return DocDbResponseJson.ok(procedureDto);
|
||||
try {
|
||||
ProcedureDto procedureDto = dbBaseService.getProcedureDetail(sourceId, dbName, typeName, procName);
|
||||
return DocDbResponseJson.ok(procedureDto);
|
||||
} catch (Exception e) {
|
||||
// 一般是数据库的帐号没权限查存储过程
|
||||
return DocDbResponseJson.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,13 +103,19 @@ public class DbProcedureController {
|
||||
*/
|
||||
@PostMapping(value = "/delete")
|
||||
public ResponseJson delete(Long sourceId, String dbName, String typeName, String procName) {
|
||||
boolean manageAuth = DocUserUtil.haveAuth(DocAuthConst.DB_DATASOURCE_MANAGE);
|
||||
if (!manageAuth) {
|
||||
return DocDbResponseJson.warn("没有该数据源的管理权限");
|
||||
this.judgeAuth(sourceId, DbAuthType.PROC_EDIT.getName(), "没有修改该库函数的权限");
|
||||
DbProcLog dbProcLog = this.createDbProcLog(sourceId, dbName, typeName, procName, "删除函数操作");
|
||||
try {
|
||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(sourceId);
|
||||
dbBaseService.deleteProcedure(sourceId, dbName, typeName, procName);
|
||||
return DocDbResponseJson.ok();
|
||||
} catch (Exception e) {
|
||||
dbProcLog.setStatus(2);
|
||||
// 一般是数据库的帐号没权限查存储过程
|
||||
return DocDbResponseJson.error(e.getMessage());
|
||||
} finally {
|
||||
dbProcLogService.save(dbProcLog);
|
||||
}
|
||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(sourceId);
|
||||
dbBaseService.deleteProcedure(sourceId, dbName, typeName, procName);
|
||||
return DocDbResponseJson.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,14 +130,93 @@ public class DbProcedureController {
|
||||
*/
|
||||
@PostMapping(value = "/save")
|
||||
public ResponseJson save(Long sourceId, String dbName, String typeName, String procName, String procSql) {
|
||||
boolean manageAuth = DocUserUtil.haveAuth(DocAuthConst.DB_DATASOURCE_MANAGE);
|
||||
if (!manageAuth) {
|
||||
return DocDbResponseJson.warn("没有该数据源的管理权限");
|
||||
this.judgeAuth(sourceId, DbAuthType.PROC_EDIT.getName(), "没有修改该库函数的权限");
|
||||
DbProcLog dbProcLog = this.createDbProcLog(sourceId, dbName, typeName, procName, procSql);
|
||||
try {
|
||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(sourceId);
|
||||
ExecuteResult executeResult = dbBaseService.saveProcedure(sourceId, dbName, typeName, procName, procSql);
|
||||
if (StringUtils.isNotBlank(executeResult.getErrMsg())) {
|
||||
dbProcLog.setStatus(2);
|
||||
}
|
||||
return DocDbResponseJson.ok(executeResult);
|
||||
} catch (Exception e) {
|
||||
dbProcLog.setStatus(2);
|
||||
// 一般是数据库的帐号没权限查存储过程
|
||||
return DocDbResponseJson.error(e.getMessage());
|
||||
} finally {
|
||||
dbProcLogService.save(dbProcLog);
|
||||
}
|
||||
DbBaseService dbBaseService = dbBaseFactory.getDbBaseService(sourceId);
|
||||
ExecuteResult executeResult = dbBaseService.saveProcedure(sourceId, dbName, typeName, procName, procSql);
|
||||
return DocDbResponseJson.ok(executeResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储过程修改日志列表
|
||||
*
|
||||
* @param sourceId 数据源ID
|
||||
* @param dbName 数据库名
|
||||
* @param typeName 类型名
|
||||
* @param procName 函数名
|
||||
* @return 列表
|
||||
*/
|
||||
@PostMapping(value = "/log/list")
|
||||
public ResponseJson logList(Integer pageNum, Integer pageSize, Long sourceId, String dbName, String typeName, String procName) {
|
||||
QueryWrapper<DbProcLog> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("datasource_id", sourceId);
|
||||
wrapper.eq("proc_db", dbName);
|
||||
wrapper.eq("proc_name", procName);
|
||||
wrapper.eq("proc_type", typeName);
|
||||
wrapper.orderByDesc("id");
|
||||
wrapper.select("id", "proc_body", "create_user_name", "create_time", "status");
|
||||
IPage<DbProcLog> page = new Page<>(pageNum, pageSize, pageNum == 1);
|
||||
dbProcLogService.page(page, wrapper);
|
||||
return DocDbResponseJson.ok(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储过程修改日志详情
|
||||
*
|
||||
* @param logId 日志ID
|
||||
* @return 详情
|
||||
*/
|
||||
@PostMapping(value = "/log/detail")
|
||||
public ResponseJson logDetail(Long logId) {
|
||||
DbProcLog dbProcLog = dbProcLogService.getById(logId);
|
||||
return DocDbResponseJson.ok(dbProcLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限判断
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
*/
|
||||
private void judgeAuth(Long sourceId, String authName, String noAuthInfo) {
|
||||
if (!DocUserUtil.haveAuth(DocAuthConst.DB_DATASOURCE_MANAGE)
|
||||
&& !DocUserUtil.haveCustomAuth(authName, DocAuthConst.DB + sourceId)) {
|
||||
throw new ConfirmException(noAuthInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建日志对象
|
||||
* @param sourceId
|
||||
* @param dbName
|
||||
* @param typeName
|
||||
* @param procName
|
||||
* @param procSql
|
||||
* @return
|
||||
*/
|
||||
public DbProcLog createDbProcLog(Long sourceId, String dbName, String typeName, String procName, String procSql) {
|
||||
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
|
||||
DbProcLog dbProcLog = new DbProcLog();
|
||||
dbProcLog.setDatasourceId(sourceId);
|
||||
dbProcLog.setCreateTime(new Date());
|
||||
dbProcLog.setCreateUserId(currentUser.getUserId());
|
||||
dbProcLog.setCreateUserName(currentUser.getUsername());
|
||||
dbProcLog.setProcDb(dbName);
|
||||
dbProcLog.setProcName(procName);
|
||||
dbProcLog.setProcType(typeName);
|
||||
dbProcLog.setProcBody(procSql);
|
||||
dbProcLog.setStatus(1);
|
||||
return dbProcLog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ public class UserDbAuthVo {
|
||||
private Long userId;
|
||||
private Integer executeAuth;
|
||||
private Integer descEditAuth;
|
||||
private Integer procEditAuth;
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
@@ -37,4 +38,12 @@ public class UserDbAuthVo {
|
||||
public void setDescEditAuth(Integer descEditAuth) {
|
||||
this.descEditAuth = descEditAuth;
|
||||
}
|
||||
|
||||
public Integer getProcEditAuth() {
|
||||
return procEditAuth;
|
||||
}
|
||||
|
||||
public void setProcEditAuth(Integer procEditAuth) {
|
||||
this.procEditAuth = procEditAuth;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ public enum DbAuthType {
|
||||
VIEW(1, "DB_VIEW_"),
|
||||
SELECT(2, "DB_SELECT_"),
|
||||
UPDATE(3, "DB_UPDATE_"),
|
||||
DESC_EDIT(3, "DB_DESC_EDIT_"),
|
||||
DESC_EDIT(4, "DB_DESC_EDIT_"),
|
||||
PROC_EDIT(5, "DB_PROC_EDIT_"),
|
||||
;
|
||||
private Integer type;
|
||||
private String name;
|
||||
|
||||
@@ -66,13 +66,13 @@ public class MysqlServiceImpl extends DbBaseService {
|
||||
// 新建的时候
|
||||
ProcedureDto procedureDetailNew = new ProcedureDto();
|
||||
if (Objects.equals(typeName, "FUNCTION")) {
|
||||
procedureDetailNew.setBody("CREATE DEFINER = CURRENT_USER " + typeName + " `" + procName + "`() RETURNS integer\n" +
|
||||
procedureDetailNew.setBody("CREATE DEFINER = CURRENT_USER " + typeName + " `" + dbName + "`.`" + procName + "`() RETURNS integer\n" +
|
||||
"BEGIN\n" +
|
||||
"\t#Routine body goes here...\n" +
|
||||
"\tRETURN 0;\n" +
|
||||
"END;");
|
||||
} else {
|
||||
procedureDetailNew.setBody("CREATE DEFINER = CURRENT_USER " + typeName + " `" + procName + "`()\n" +
|
||||
procedureDetailNew.setBody("CREATE DEFINER = CURRENT_USER " + typeName + " `" + dbName + "`.`" + procName + "`()\n" +
|
||||
"BEGIN\n" +
|
||||
"\t#Routine body goes here...\n" +
|
||||
"END;");
|
||||
@@ -85,9 +85,10 @@ public class MysqlServiceImpl extends DbBaseService {
|
||||
// 组装好SQL
|
||||
String type = procedureDetail.getType();
|
||||
String name = procedureDetail.getName();
|
||||
String db = procedureDetail.getDb();
|
||||
String paramList = StringUtils.defaultIfBlank(procedureDetail.getParamList(), "");
|
||||
String[] definerArr = procedureDetail.getDefiner().split("@");
|
||||
String createStr = String.format("CREATE DEFINER=`%s`@`%s` %s `%s`(%s)", definerArr[0], definerArr[1], type, name, paramList);
|
||||
String createStr = String.format("CREATE DEFINER=`%s`@`%s` %s `%s`.`%s`(%s)", definerArr[0], definerArr[1], type, db, name, paramList);
|
||||
if (Objects.equals(procedureDetail.getType(), "FUNCTION")) {
|
||||
createStr += " RETURNS " + procedureDetail.getReturns();
|
||||
}
|
||||
@@ -99,7 +100,7 @@ public class MysqlServiceImpl extends DbBaseService {
|
||||
public ExecuteResult saveProcedure(Long sourceId, String dbName, String typeName, String procName, String procSql) {
|
||||
String firstLine = procSql.split("\n")[0];
|
||||
// 看函数名是否被修改了,修改会导致函数名的不确定,有认知上的成本,明确的先删再建吧
|
||||
if (!firstLine.contains(" `" + procName + "`(") && !firstLine.contains(" " + procName + "(")) {
|
||||
if (!firstLine.contains("`" + procName + "`(") && !firstLine.contains(" " + procName + "(") && !firstLine.contains("." + procName + "(")) {
|
||||
return ExecuteResult.error("在编辑页面不允许修改函数名,如需新建或修改,请到列表页删除后再新建函数", procSql);
|
||||
}
|
||||
ProcedureDto procedureDetail = this.getProcedureDetail(sourceId, dbName, typeName, procName);
|
||||
@@ -121,7 +122,7 @@ public class MysqlServiceImpl extends DbBaseService {
|
||||
executeParam.setSql(procedureDetail.getBody());
|
||||
sqlExecutor.execute(executeParam);
|
||||
} catch (Exception e1) {
|
||||
return ExecuteResult.error("执行和恢复函数均失败,请先备份您的SQL,以防丢失", procSql);
|
||||
return ExecuteResult.error("执行和恢复函数均失败,请先备份您的SQL,以防丢失\n" + e.getMessage(), procSql);
|
||||
}
|
||||
return ExecuteResult.error(e.getMessage(), procSql);
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon-db.png><title>数据库文档管理</title><link href=css/app.b6b9fe42.css rel=preload as=style><link href=css/chunk-vendors.8924efc6.css rel=preload as=style><link href=js/app.069b56af.js rel=preload as=script><link href=js/chunk-vendors.d40f789d.js rel=preload as=script><link href=css/chunk-vendors.8924efc6.css rel=stylesheet><link href=css/app.b6b9fe42.css rel=stylesheet></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.d40f789d.js></script><script src=js/app.069b56af.js></script></body></html>
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon-db.png><title>数据库文档管理</title><link href=css/app.b6b9fe42.css rel=preload as=style><link href=css/chunk-vendors.8924efc6.css rel=preload as=style><link href=js/app.a7f24e90.js rel=preload as=script><link href=js/chunk-vendors.d40f789d.js rel=preload as=script><link href=css/chunk-vendors.8924efc6.css rel=stylesheet><link href=css/app.b6b9fe42.css rel=stylesheet></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.d40f789d.js></script><script src=js/app.a7f24e90.js></script></body></html>
|
||||
File diff suppressed because one or more lines are too long
@@ -55,6 +55,7 @@ INSERT INTO `auth_info` VALUES (14, 'DB_VIEW_', '数据源查看权', 0, 1, '201
|
||||
INSERT INTO `auth_info` VALUES (15, 'DB_SELECT_', '数据源查询权', 0, 1, '2019-08-18 23:25:17', 0);
|
||||
INSERT INTO `auth_info` VALUES (16, 'DB_UPDATE_', '数据源增删改查权', 0, 1, '2019-08-18 23:25:17', 0);
|
||||
INSERT INTO `auth_info` VALUES (17, 'DB_DESC_EDIT_', '表字段注释修改权', 0, 1, '2019-08-18 23:25:17', 0);
|
||||
INSERT INTO `auth_info` VALUES (18, 'DB_PROC_EDIT_', '存储过程修改权', 0, 1, '2021-04-24 23:25:17', 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for db_datasource
|
||||
@@ -467,7 +468,7 @@ CREATE TABLE `wiki_space_favorite` (
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户空间收藏记录表';
|
||||
|
||||
DROP TABLE IF EXISTS `wiki_space_favorite`;
|
||||
DROP TABLE IF EXISTS `user_setting`;
|
||||
CREATE TABLE `user_setting` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
|
||||
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
|
||||
@@ -478,5 +479,20 @@ CREATE TABLE `user_setting` (
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户设置表';
|
||||
|
||||
DROP TABLE IF EXISTS `db_proc_log`;
|
||||
CREATE TABLE `db_proc_log` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
|
||||
`datasource_id` bigint(20) DEFAULT NULL COMMENT '数据源ID',
|
||||
`proc_db` varchar(100) DEFAULT NULL COMMENT '所属数据库',
|
||||
`proc_name` varchar(100) DEFAULT NULL COMMENT '名字',
|
||||
`proc_type` varchar(50) DEFAULT NULL COMMENT '类型',
|
||||
`proc_body` longblob DEFAULT NULL COMMENT '函数创建SQL',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '保存状态 1=成功 2=失败',
|
||||
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
|
||||
`create_user_name` varchar(20) DEFAULT NULL COMMENT '创建人名字',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='数据库函数修改日志';
|
||||
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
@@ -58,4 +58,22 @@ CREATE TABLE `user_setting` (
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户设置表';
|
||||
|
||||
CREATE TABLE `db_proc_log` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
|
||||
`datasource_id` bigint(20) DEFAULT NULL COMMENT '数据源ID',
|
||||
`proc_db` varchar(100) DEFAULT NULL COMMENT '所属数据库',
|
||||
`proc_name` varchar(100) DEFAULT NULL COMMENT '名字',
|
||||
`proc_type` varchar(50) DEFAULT NULL COMMENT '类型',
|
||||
`proc_body` longblob DEFAULT NULL COMMENT '函数创建SQL',
|
||||
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '保存状态 1=成功 2=失败',
|
||||
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人ID',
|
||||
`create_user_name` varchar(20) DEFAULT NULL COMMENT '创建人名字',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='数据库函数修改日志';
|
||||
|
||||
INSERT INTO `auth_info`(auth_name, auth_desc, can_edit, create_uid, creation_time, auth_type)
|
||||
VALUES ('DB_PROC_EDIT_', '存储过程修改权', 0, 1, '2021-04-24 23:25:17', 0);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -95,6 +95,12 @@ export default {
|
||||
saveProcedure: data => {
|
||||
return request({url: '/zyplayer-doc-db/procedure/save', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
procedureLogList: data => {
|
||||
return request({url: '/zyplayer-doc-db/procedure/log/list', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
procedureLogDetail: data => {
|
||||
return request({url: '/zyplayer-doc-db/procedure/log/detail', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
systemUpgradeInfo: data => {
|
||||
return request({url: '/system/info/upgrade', method: 'post', data: Qs.stringify(data)});
|
||||
},
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
<span style="margin-left: 10px;color: #999;font-size: 12px;"><i class="el-icon-info"></i> 添加、删除或编辑之后记得点击保存哦~</span>
|
||||
</span>
|
||||
<el-row>
|
||||
<el-select v-model="dbSourceAuthNewUser" filterable remote reserve-keyword
|
||||
<el-select v-model="dbSourceAuthNewUser" filterable remote reserve-keyword autoComplete="new-password"
|
||||
placeholder="请输入名字、邮箱、账号搜索用户" :remote-method="getSearchUserList"
|
||||
:loading="dbSourceAuthUserLoading" style="width: 750px;margin-right: 10px;">
|
||||
<el-option v-for="item in searchUserList" :key="item.id" :label="item.userName" :value="item.id"></el-option>
|
||||
@@ -94,11 +94,14 @@
|
||||
<el-table-column prop="userName" label="用户" width="150"></el-table-column>
|
||||
<el-table-column label="权限">
|
||||
<template slot-scope="scope">
|
||||
<el-radio v-model="scope.row.executeAuth" :label="0">无权限</el-radio>
|
||||
<el-radio v-model="scope.row.executeAuth" :label="1">库表查看权</el-radio>
|
||||
<el-radio v-model="scope.row.executeAuth" :label="2">数据查询权</el-radio>
|
||||
<el-radio v-model="scope.row.executeAuth" :label="3">所有权限</el-radio>
|
||||
<el-select v-model="scope.row.executeAuth" placeholder="选择权限" style="width: 150px;margin-right: 10px;">
|
||||
<el-option value="">无权限</el-option>
|
||||
<el-option :value="1" label="库表查看权"></el-option>
|
||||
<el-option :value="2" label="数据查询权"></el-option>
|
||||
<el-option :value="3" label="所有权限"></el-option>
|
||||
</el-select>
|
||||
<el-checkbox :true-label="1" :false-label="0" v-model="scope.row.descEditAuth">表字段注释修改权</el-checkbox>
|
||||
<el-checkbox :true-label="1" :false-label="0" v-model="scope.row.procEditAuth">函数修改权</el-checkbox>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
@@ -201,8 +204,9 @@
|
||||
this.dbSourceAuthUserList.push({
|
||||
userName: userName,
|
||||
userId: this.dbSourceAuthNewUser,
|
||||
executeAuth: 0,
|
||||
executeAuth: '',
|
||||
descEditAuth: 0,
|
||||
procEditAuth: 0,
|
||||
});
|
||||
this.dbSourceAuthNewUser = "";
|
||||
},
|
||||
@@ -292,6 +296,8 @@
|
||||
setTimeout(() => {
|
||||
this.loadDataListLoading = false;
|
||||
}, 800);
|
||||
}).catch(() => {
|
||||
this.loadDataListLoading = false;
|
||||
});
|
||||
},
|
||||
getDatasourceGroupList() {
|
||||
|
||||
@@ -55,11 +55,11 @@
|
||||
</div>
|
||||
<div style="padding: 10px;" v-loading="columnListLoading">
|
||||
<el-table :data="columnList" stripe border style="width: 100%; margin-bottom: 5px;">
|
||||
<el-table-column prop="name" label="字段名" width="200"></el-table-column>
|
||||
<el-table-column prop="name" label="字段名" width="220"></el-table-column>
|
||||
<el-table-column label="自增" width="50">
|
||||
<template slot-scope="scope">{{scope.row.isidentity ? '是' : '否'}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="类型" width="150"></el-table-column>
|
||||
<el-table-column prop="type" label="类型" width="180"></el-table-column>
|
||||
<el-table-column prop="length" label="长度" width="80"></el-table-column>
|
||||
<el-table-column prop="nullable" label="空值" width="80"></el-table-column>
|
||||
<el-table-column label="主键" width="50">
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
}
|
||||
this.procedureList = json.data || [];
|
||||
this.procedureListLoading = false;
|
||||
}).catch(() => {
|
||||
this.procedureListLoading = false;
|
||||
});
|
||||
},
|
||||
doEditProc(item) {
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
<el-card style="margin: 10px;" shadow="never" v-loading="procedureInfoLoading">
|
||||
<div slot="header" class="clearfix">
|
||||
<span style="margin-right: 20px;">编辑函数</span>
|
||||
<el-button type="" @click="saveProcedure" icon="el-icon-document-checked" size="mini">保存</el-button>
|
||||
<el-button type="primary" @click="saveProcedure" icon="el-icon-document-checked" size="mini">保存</el-button>
|
||||
<el-button type="" @click="showProcedureLog" icon="el-icon-document" size="mini">修改日志</el-button>
|
||||
<!-- <el-button type="" @click="" icon="el-icon-video-play" size="mini">运行</el-button>-->
|
||||
<!-- <el-button type="" @click="" icon="el-icon-video-pause" size="mini">停止</el-button>-->
|
||||
</div>
|
||||
@@ -24,6 +25,36 @@
|
||||
<pre>{{saveProcedureErrInfo}}</pre>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!--函数修改日志弹窗-->
|
||||
<el-dialog title="函数修改日志" :visible.sync="procLogVisible" :footer="null">
|
||||
<el-table :data="procLogList" stripe border style="width: 100%;" height="400">
|
||||
<el-table-column prop="id" label="ID" width="100"></el-table-column>
|
||||
<el-table-column prop="createUserName" label="修改人"></el-table-column>
|
||||
<el-table-column prop="createTime" label="修改时间"></el-table-column>
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success" v-if="scope.row.status==1">保存成功</el-tag>
|
||||
<el-tag type="danger" v-else-if="scope.row.status==2">保存失败</el-tag>
|
||||
<el-tag type="danger" v-else>-</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="action" label="操作" width="130">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="" @click="reEditProc(scope.row.id)">重新编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="margin-top: 10px;"
|
||||
@size-change="handlePageSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="currentPage"
|
||||
:page-sizes="[10, 30, 50]"
|
||||
:page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableTotalCount">
|
||||
</el-pagination>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -44,6 +75,12 @@
|
||||
sqlExecutorEditor: {},
|
||||
saveProcedureErrInfo: '',
|
||||
saveProcedureErrVisible: false,
|
||||
// 日志列表
|
||||
procLogVisible: false,
|
||||
procLogList: [],
|
||||
pageSize: 30,
|
||||
currentPage: 1,
|
||||
tableTotalCount: 0,
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
@@ -74,12 +111,43 @@
|
||||
let newName = {key: this.$route.fullPath, val: '编辑函数-' + this.vueQueryParam.procName};
|
||||
this.$store.commit('global/addTableName', newName);
|
||||
},
|
||||
handleCurrentChange(to) {
|
||||
this.currentPage = to;
|
||||
this.searchProcedureLogList();
|
||||
},
|
||||
handlePageSizeChange(to) {
|
||||
this.pageSize = to;
|
||||
this.searchProcedureLogList();
|
||||
},
|
||||
showProcedureLog() {
|
||||
this.currentPage = 1;
|
||||
this.procLogVisible = true;
|
||||
this.searchProcedureLogList();
|
||||
},
|
||||
searchProcedureLogList() {
|
||||
let param = {...this.vueQueryParam, ...this.searchParam, pageNum: this.currentPage, pageSize: this.pageSize};
|
||||
datasourceApi.procedureLogList(param).then(json => {
|
||||
if (this.currentPage == 1) {
|
||||
this.tableTotalCount = json.total || 0;
|
||||
}
|
||||
this.procLogList = json.data || [];
|
||||
});
|
||||
},
|
||||
reEditProc(id) {
|
||||
datasourceApi.procedureLogDetail({logId: id}).then(json => {
|
||||
let procedureLog = json.data || {};
|
||||
this.sqlExecutorEditor.setValue(procedureLog.procBody, 1);
|
||||
this.procLogVisible = false;
|
||||
});
|
||||
},
|
||||
searchProcedureDetail() {
|
||||
this.procedureInfoLoading = true;
|
||||
datasourceApi.procedureDetail(this.vueQueryParam).then(json => {
|
||||
this.procedureInfo = json.data || {};
|
||||
this.procedureInfoLoading = false;
|
||||
this.sqlExecutorEditor.setValue(this.procedureInfo.body, 1);
|
||||
}).catch(() => {
|
||||
this.procedureInfoLoading = false;
|
||||
});
|
||||
},
|
||||
saveProcedure() {
|
||||
@@ -94,6 +162,8 @@
|
||||
} else {
|
||||
this.$message.success("保存成功!");
|
||||
}
|
||||
}).catch(() => {
|
||||
this.procedureInfoLoading = false;
|
||||
});
|
||||
},
|
||||
doDeleteProc(item) {
|
||||
|
||||
Reference in New Issue
Block a user