1. 增加操作日志接口

This commit is contained in:
黄昕 2024-03-08 10:45:00 +08:00
parent 8ad48367ab
commit 95e7c5f0ab
20 changed files with 477 additions and 62 deletions

View File

@ -1,4 +1,4 @@
package com.cf.cs.database.pojo.po;
package com.cf.cs.base.pojo.po;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;

View File

@ -1,4 +1,4 @@
package com.cf.cs.web.setup;
package com.cf.cs.base.setup;
import com.cf.cs.base.config.CommonConfigure;
import lombok.extern.slf4j.Slf4j;

View File

@ -1,31 +0,0 @@
package com.cf.cs.database.pojo.po;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* The type Operation log details.
*
* @author xajhuang @163.com
*/
@Schema(name = "系统操作日志详细信息")
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OperationLogDetails {
@Schema(description = "id")
private Long id;
@Schema(description = "HTTP 请求头所有参数")
private String requestHeaders;
@Schema(description = "操作请求参数")
private String request;
@Schema(description = "操作返回结果")
private String result;
}

View File

@ -3,8 +3,6 @@ package com.cf.cs.database.service;
import com.cf.cs.base.annotation.OperationLogAnnotation;
import com.cf.cs.base.common.ErrorCode;
import com.cf.cs.database.pojo.entity.OperationLog;
import com.cf.cs.database.pojo.po.OperationLogDetails;
import com.cf.cs.database.pojo.po.OperationLogSummary;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService;
import jakarta.servlet.http.HttpServletRequest;
@ -67,7 +65,7 @@ public interface OperationLogDataBaseService extends IService<OperationLog> {
* @param userName the username
* @return the system operation summary
*/
Page<OperationLogSummary> getSystemOperationSummary(Long pageNumber, Long pageSize, Long totalSize, List<String> userName);
Page<OperationLog> getSystemOperationSummary(Long pageNumber, Long pageSize, Long totalSize, List<String> userName);
/**
* Gets system operation details.
@ -75,5 +73,5 @@ public interface OperationLogDataBaseService extends IService<OperationLog> {
* @param operationId the operation id
* @return the system operation details
*/
List<OperationLogDetails> getSystemOperationDetails(List<Long> operationId);
List<OperationLog> getSystemOperationDetails(List<Long> operationId);
}

View File

@ -2,7 +2,7 @@ package com.cf.cs.database.service;
import com.cf.cs.database.pojo.entity.User;
import com.cf.cs.database.pojo.po.PageResults;
import com.cf.cs.base.pojo.po.PageResults;
import com.cf.cs.database.pojo.po.ResPermInfo;
import com.cf.cs.database.pojo.po.UserInfo;
import com.mybatisflex.core.service.IService;

View File

@ -9,8 +9,6 @@ import com.cf.cs.base.misc.HelperUtils;
import com.cf.cs.base.pojo.po.ApiContext;
import com.cf.cs.database.mapper.OperationLogMapper;
import com.cf.cs.database.pojo.entity.OperationLog;
import com.cf.cs.database.pojo.po.OperationLogDetails;
import com.cf.cs.database.pojo.po.OperationLogSummary;
import com.cf.cs.database.service.OperationLogDataBaseService;
import com.cf.cs.database.service.UserDataBaseService;
import com.jayway.jsonpath.JsonPath;
@ -142,7 +140,7 @@ public class OperationLogDataBaseServiceImpl extends ServiceImpl<OperationLogMap
}
@Override
public Page<OperationLogSummary> getSystemOperationSummary(Long pageNumber,
public Page<OperationLog> getSystemOperationSummary(Long pageNumber,
Long pageSize,
Long totalSize,
List<String> userName) {
@ -179,7 +177,7 @@ public class OperationLogDataBaseServiceImpl extends ServiceImpl<OperationLogMap
ctx.getId())))));
}
return operationLogMapper.paginateAs(pageNumber, pageSize, totalSize, wrapper, OperationLogSummary.class);
return operationLogMapper.paginate(pageNumber, pageSize, totalSize, wrapper);
} else {
log.error("Current User is not authentication.");
throw new CommonErrorCodeException(ErrorCode.ERR_LOGOUT);
@ -187,12 +185,12 @@ public class OperationLogDataBaseServiceImpl extends ServiceImpl<OperationLogMap
}
@Override
public List<OperationLogDetails> getSystemOperationDetails(List<Long> operationId) {
public List<OperationLog> getSystemOperationDetails(List<Long> operationId) {
QueryWrapper wrapper = QueryWrapper.create()
.from(OPERATION_LOG)
.select()
.where(OPERATION_LOG.ID.in(operationId));
return operationLogMapper.selectListByQueryAs(wrapper, OperationLogDetails.class);
return operationLogMapper.selectListByQuery(wrapper);
}
@Override

View File

@ -14,7 +14,7 @@ import com.cf.cs.database.mapper.UserMapper;
import com.cf.cs.database.pojo.entity.ResourceData;
import com.cf.cs.database.pojo.entity.RoleResource;
import com.cf.cs.database.pojo.entity.User;
import com.cf.cs.database.pojo.po.PageResults;
import com.cf.cs.base.pojo.po.PageResults;
import com.cf.cs.database.pojo.po.ResPermInfo;
import com.cf.cs.database.pojo.po.UserInfo;
import com.cf.cs.database.service.UserDataBaseService;

View File

@ -0,0 +1,39 @@
package com.cf.cs.protocol.pojo.dto;
import com.cf.cs.protocol.validation.group.ValidGroups;
import com.cf.cs.protocol.validation.valids.ValidPageSize;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* The type Base paged req.
*
* @author xajhuang @163.com
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "BasePagedReq", description = "分页请求基础参数")
public class BasePagedReq {
@Schema(description = "分页号最小值为1")
@NotNull(message = "pageNumber 必须指定分页配置", groups = ValidGroups.BasePagedReqValid.class)
@Min(value = 1, message = "pageNumber 最小值为1", groups = ValidGroups.BasePagedReqValid.class)
private Long pageNumber;
@Schema(description = "分页大小最小值为5 最大值100 取值必须为5的整数倍")
@NotNull(message = "pageSize 必须指定分页配置", groups = ValidGroups.BasePagedReqValid.class)
@ValidPageSize(message = "pageSize 取值必须为 5 的整数倍", groups = ValidGroups.BasePagedReqValid.class)
@Min(value = 5, message = "pageSize 最小值为5", groups = ValidGroups.BasePagedReqValid.class)
@Max(value = 100, message = "pageSize 最大值为100", groups = ValidGroups.BasePagedReqValid.class)
private Long pageSize;
@Schema(description = "数据总数未知时可以为空或者小于0 存在时可以加快后端数据库查询速度")
private Long totalSize;
}

View File

@ -0,0 +1,31 @@
package com.cf.cs.protocol.pojo.dto;
import com.cf.cs.protocol.validation.group.ValidGroups;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* The type Operation log details req.
*
* @author xajhuang @163.com
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "OperationLogDetailsReq", description = "操作日志详细请求参数")
public class OperationLogDetailsReq {
@Schema(description = "操作日志ID")
@NotEmpty(message = "操作日志ID不能为空", groups = ValidGroups.OperationLogReqValid.class)
@Size(message = "操作日志ID至少需要指定 1 个,最多只能指定 100 个", min = 1, max = 100, groups = ValidGroups.OperationLogReqValid.class)
private List<Long> operationIds;
}

View File

@ -0,0 +1,26 @@
package com.cf.cs.protocol.pojo.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* The type Operation log req.
*
* @author xajhuang @163.com
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "OperationLogReq", description = "操作日志摘要信息请求参数")
public class OperationLogReq extends BasePagedReq {
@Schema(description = "用户名, 需要查询指定用户的操作日志时指定用户, 支持同时指定多个用户, 分页查询过程中该参数不能改变")
private List<String> userName;
}

View File

@ -0,0 +1,49 @@
package com.cf.cs.protocol.pojo.po;
import com.cf.cs.base.common.ErrorCode;
import com.cf.cs.protocol.pojo.po.BaseRespStatus;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* The type Opt log details resp.
*
* @author xajhuang @163.com
*/
@Schema(name = "系统操作日志详细信息")
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"id", "requestHeaders", "request", "result", "status", "message"})
public class OptLogDetails extends BaseRespStatus {
@Schema(description = "id")
private Long id;
@Schema(description = "HTTP 请求头所有参数")
private String requestHeaders;
@Schema(description = "操作请求参数")
private String request;
@Schema(description = "操作返回结果")
private String result;
/**
* Instantiates a new Opt log details resp.
*
* @param id the id
* @param error the error
*/
public OptLogDetails(Long id, ErrorCode error) {
this.id = id;
this.setStatus(error.getCode());
this.setMessage(new String[] {error.getDescription()});
}
}

View File

@ -0,0 +1,28 @@
package com.cf.cs.protocol.pojo.vo;
import com.cf.cs.base.pojo.po.PageResults;
import com.cf.cs.protocol.pojo.po.BaseRespStatus;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* The type Base page result resp.
*
* @param <T> the type parameter
* @author xajhuang @163.com
*/
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"items", "status", "message"})
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BasePageResultResp<T> extends BaseRespStatus {
private PageResults<T> items;
}

View File

@ -0,0 +1,27 @@
package com.cf.cs.protocol.pojo.vo;
import com.cf.cs.protocol.pojo.po.BaseRespStatus;
import com.cf.cs.protocol.pojo.po.OptLogDetails;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* The type Operation log details resp.
*
* @author xajhuang @163.com
*/
@EqualsAndHashCode(callSuper = true)
@Data
@JsonPropertyOrder({"operationLog", "status", "message"})
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class OperationLogDetailsResp extends BaseRespStatus {
private List<OptLogDetails> operationLog;
}

View File

@ -1,4 +1,4 @@
package com.cf.cs.database.pojo.po;
package com.cf.cs.protocol.pojo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -6,13 +6,13 @@ import lombok.Data;
import java.sql.Timestamp;
/**
* The type Operation log summary.
* The type Opt log summary resp.
*
* @author xajhuang @163.com
*/
@Schema(name = "系统操作日志摘要数据")
@Data
public class OperationLogSummary {
public class OptLogSummaryResp {
@Schema(description = "id")
private Long id;

View File

@ -48,6 +48,16 @@
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</dependency>
<dependency>
<groupId>com.cf.cs</groupId>
@ -67,18 +77,6 @@
<version>${cs-package.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.cf.cs</groupId>
<artifactId>cs-services</artifactId>
<version>${cs-package.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.cf.cs</groupId>
<artifactId>cs-web</artifactId>
<version>${cs-package.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.cf.cs</groupId>
<artifactId>cs-authentication</artifactId>

View File

@ -8,8 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*
* @author xajhuang @163.com
*/
@SpringBootApplication(scanBasePackages = {"com.cf.cs.base", "com.cf.cs.database", "com.cf.cs.protocol", "com.cf.cs.authentication",
"com.cf.cs.services", "com.cf.cs.restful", "com.cf.cs.web"})
@SpringBootApplication(scanBasePackages = {"com.cf.cs.base", "com.cf.cs.database", "com.cf.cs.protocol",
"com.cf.cs.authentication", "com.cf.cs.restful"})
public class CsRestfulApplication {
/**

View File

@ -0,0 +1,100 @@
package com.cf.cs.restful.controller;
import com.cf.cs.base.annotation.OperationLogAnnotation;
import com.cf.cs.base.common.ErrorCode;
import com.cf.cs.base.misc.HelperUtils;
import com.cf.cs.crypto.annotation.EncryptionProtocol;
import com.cf.cs.base.pojo.po.PageResults;
import com.cf.cs.protocol.pojo.dto.OperationLogDetailsReq;
import com.cf.cs.protocol.pojo.dto.OperationLogReq;
import com.cf.cs.protocol.pojo.dto.ProtocolReq;
import com.cf.cs.protocol.pojo.po.BaseRespStatus;
import com.cf.cs.protocol.pojo.po.OptLogDetails;
import com.cf.cs.protocol.pojo.vo.BasePageResultResp;
import com.cf.cs.protocol.pojo.vo.OperationLogDetailsResp;
import com.cf.cs.protocol.pojo.vo.OptLogSummaryResp;
import com.cf.cs.protocol.pojo.vo.ProtocolResp;
import com.cf.cs.protocol.validation.group.ValidGroups;
import com.cf.cs.restful.service.OperationLogService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* The type Operation log api.
*
* @author xajhuang @163.com
*/
@RestController
@Slf4j
@Tag(name = "操作日志接口")
@RequestMapping(value = "/api/operation")
public class OperationLogApi {
@Resource
private OperationLogService operationLogService;
/**
* Gets summary.
*
* @param mr the mr
* @return the summary
*/
@PostMapping("/summary")
@EncryptionProtocol
@OperationLogAnnotation(OperationModule = "操作日志模块", OperationType = "读取", OperationDesc = "获取操作日志简要信息")
public ProtocolResp<? extends BaseRespStatus> getSummary(@RequestBody ProtocolReq<OperationLogReq> mr) {
List<String> validate = HelperUtils.validate(mr, ValidGroups.ProtocolCommonValid.class,
ValidGroups.BasePagedReqValid.class,
ValidGroups.OperationLogReqValid.class);
// 如果校验通过validate为空否则validate包含未校验通过项
if (validate.isEmpty()) {
OperationLogReq req = mr.getMsgContent();
PageResults<OptLogSummaryResp> ret = operationLogService.getOperationLogSummary(req.getPageNumber(), req.getPageSize(),
req.getTotalSize(), req.getUserName());
return ProtocolResp.result(BasePageResultResp.<OptLogSummaryResp>builder()
.items(ret)
.build());
} else {
return ProtocolResp.result(ErrorCode.ERR_PARAMEXCEPTION,
ErrorCode.ERR_PARAMEXCEPTION.getHttpCode(),
validate.toArray(new String[0]));
}
}
/**
* Gets details.
*
* @param mr the mr
* @return the details
*/
@PostMapping("/details")
@EncryptionProtocol
@OperationLogAnnotation(OperationModule = "操作日志模块", OperationType = "读取", OperationDesc = "获取操作日志详细信息")
public ProtocolResp<? extends BaseRespStatus> getDetails(@RequestBody ProtocolReq<OperationLogDetailsReq> mr) {
List<String> validate = HelperUtils.validate(mr, ValidGroups.ProtocolCommonValid.class,
ValidGroups.OperationLogReqValid.class);
// 如果校验通过validate为空否则validate包含未校验通过项
if (validate.isEmpty()) {
OperationLogDetailsReq req = mr.getMsgContent();
List<OptLogDetails> ret = operationLogService.getOperationLogDetails(req.getOperationIds());
return ProtocolResp.result(OperationLogDetailsResp.builder()
.operationLog(ret)
.build());
} else {
return ProtocolResp.result(ErrorCode.ERR_PARAMEXCEPTION,
ErrorCode.ERR_PARAMEXCEPTION.getHttpCode(),
validate.toArray(new String[0]));
}
}
}

View File

@ -0,0 +1,56 @@
package com.cf.cs.restful.pojo.mapper;
import com.cf.cs.database.pojo.entity.OperationLog;
import com.cf.cs.protocol.pojo.po.OptLogDetails;
import com.cf.cs.protocol.pojo.vo.OptLogSummaryResp;
import org.mapstruct.IterableMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* The interface Object convert.
*
* @author xajhuang @163.com
*/
@Mapper
public interface IObjectConvert {
/**
* The constant INSTANCE.
*/
IObjectConvert INSTANCE = Mappers.getMapper(IObjectConvert.class);
/**
* To opt log summary resp opt log summary resp.
*
* @param optLog the opt log
* @return the opt log summary resp
*/
List<OptLogSummaryResp> toOptLogSummaryResp(List<OperationLog> optLog);
/**
* To opt log details resp opt log details resp.
*
* @param optLog the opt log
* @return the opt log details resp
*/
@IterableMapping(qualifiedByName="toOptLogDetails")
List<OptLogDetails> toOptLogDetailsArray(List<OperationLog> optLog);
/**
* To opt log details opt log details.
*
* @param optLog the opt log
* @return the opt log details
*/
@Named("toOptLogDetails")
@Mappings(value = {
@Mapping(target = "status", ignore = true),
@Mapping(target = "message", ignore = true)
})
OptLogDetails toOptLogDetails(OperationLog optLog);
}

View File

@ -0,0 +1,34 @@
package com.cf.cs.restful.service;
import com.cf.cs.base.pojo.po.PageResults;
import com.cf.cs.protocol.pojo.po.OptLogDetails;
import com.cf.cs.protocol.pojo.vo.OptLogSummaryResp;
import java.util.List;
/**
* The interface Operation log service.
*
* @author xajhuang @163.com
*/
public interface OperationLogService {
/**
* Gets operation log summary.
*
* @param pageNumber the page number
* @param pageSize the page size
* @param totalSize the total size
* @param userName the user name
* @return the operation log summary
*/
PageResults<OptLogSummaryResp> getOperationLogSummary(Long pageNumber, Long pageSize, Long totalSize, List<String> userName);
/**
* Gets operation log details.
*
* @param optLogIds the opt log ids
* @return the operation log details
*/
List<OptLogDetails> getOperationLogDetails(List<Long> optLogIds);
}

View File

@ -0,0 +1,62 @@
package com.cf.cs.restful.service.impl;
import com.cf.cs.base.common.ErrorCode;
import com.cf.cs.database.pojo.entity.OperationLog;
import com.cf.cs.base.pojo.po.PageResults;
import com.cf.cs.database.service.OperationLogDataBaseService;
import com.cf.cs.protocol.pojo.po.OptLogDetails;
import com.cf.cs.protocol.pojo.vo.OptLogSummaryResp;
import com.cf.cs.restful.pojo.mapper.IObjectConvert;
import com.cf.cs.restful.service.OperationLogService;
import com.mybatisflex.core.paginate.Page;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* The type Operation log service.
*
* @author xajhuang @163.com
*/
@Service
public class OperationLogServiceImpl implements OperationLogService {
@Resource
private OperationLogDataBaseService operationLogDataBaseService;
@Override
public PageResults<OptLogSummaryResp> getOperationLogSummary(Long pageNumber, Long pageSize, Long totalSize, List<String> userName) {
if (totalSize == 0) {
totalSize = -1L;
}
Page<OperationLog> optLogs = operationLogDataBaseService.getSystemOperationSummary(pageNumber, pageSize, totalSize, userName);
return PageResults.<OptLogSummaryResp>builder()
.items(IObjectConvert.INSTANCE.toOptLogSummaryResp(optLogs.getRecords()))
.pageNumber(optLogs.getPageNumber())
.pageSize(optLogs.getPageSize())
.totalPage(optLogs.getTotalPage())
.totalRow(optLogs.getTotalRow())
.build();
}
@Override
public List<OptLogDetails> getOperationLogDetails(List<Long> optLogIds) {
List<OperationLog> optLogs = operationLogDataBaseService.getSystemOperationDetails(optLogIds);
List<OptLogDetails> ret = IObjectConvert.INSTANCE.toOptLogDetailsArray(optLogs);
List<OptLogDetails> notFound = optLogIds.stream()
.filter(k -> !ret.stream()
.map(OptLogDetails::getId)
.toList().contains(k))
.map(m -> new OptLogDetails(m, ErrorCode.ERR_NOSUCHITEM))
.toList();
ret.forEach(k -> {
k.setMessage(new String[] {ErrorCode.ERR_OK.getDescription()});
k.setStatus(ErrorCode.ERR_OK.getCode());
});
ret.addAll(notFound);
return ret;
}
}