Browse Source
* rebase * update audit log type name * fix the quoted property error * fix bug * update audit global switch default value * fix wrong ddl comment * fix wrong code style * update audit log search sql * add licenses * add unit test * fix wrong code style * fix bugs * fix wrong code style * add test case * add test case * add license * Add unit test in pom.xml * resolve code smell problem * mysql and postgresql ddl update * update audit log path and audit page query * update audit configuration * update audit log schema, add resource type and resource id * update audit query and list page * resolve audit log front page bugs and log query error * update audit configuration * resolve wrong configuration * update AuditLogControllerTest * update application.yaml * resolve code smell * update standalone configuration * resolve bugs Co-authored-by: yc322 <1393242780@qq.com>3.0.0/version-upgrade
41 changed files with 1895 additions and 0 deletions
@ -0,0 +1,94 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.audit; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.AuditOperationType; |
||||
import org.apache.dolphinscheduler.common.enums.AuditResourceType; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class AuditMessage { |
||||
private User user; |
||||
|
||||
private Date auditDate; |
||||
|
||||
private AuditResourceType resourceType; |
||||
|
||||
private AuditOperationType operation; |
||||
|
||||
private Integer resourceId; |
||||
|
||||
public AuditMessage(User user, Date auditDate, AuditResourceType resourceType, AuditOperationType operation, Integer resourceId) { |
||||
this.user = user; |
||||
this.auditDate = auditDate; |
||||
this.resourceType = resourceType; |
||||
this.operation = operation; |
||||
this.resourceId = resourceId; |
||||
} |
||||
|
||||
public User getUser() { |
||||
return user; |
||||
} |
||||
|
||||
public void setUser(User user) { |
||||
this.user = user; |
||||
} |
||||
|
||||
public Date getAuditDate() { |
||||
return auditDate; |
||||
} |
||||
|
||||
public void setAuditDate(Date auditDate) { |
||||
this.auditDate = auditDate; |
||||
} |
||||
|
||||
public AuditResourceType getResourceType() { |
||||
return resourceType; |
||||
} |
||||
|
||||
public void setResourceType(AuditResourceType resourceType) { |
||||
this.resourceType = resourceType; |
||||
} |
||||
|
||||
public AuditOperationType getOperation() { |
||||
return operation; |
||||
} |
||||
|
||||
public void setOperation(AuditOperationType operation) { |
||||
this.operation = operation; |
||||
} |
||||
|
||||
public Integer getResourceId() { |
||||
return resourceId; |
||||
} |
||||
|
||||
public void setResourceId(Integer resourceId) { |
||||
this.resourceId = resourceId; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "AuditMessage{" |
||||
+ "user=" + user |
||||
+ ", Date=" + auditDate |
||||
+ ", resourceType" + resourceType |
||||
+ ", operation=" + operation |
||||
+ ", resourceId='" + resourceId + '\''; |
||||
} |
||||
} |
@ -0,0 +1,93 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.audit; |
||||
|
||||
import org.apache.dolphinscheduler.api.configuration.AuditConfiguration; |
||||
|
||||
import java.util.List; |
||||
import java.util.concurrent.BlockingQueue; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
public class AuditPublishService { |
||||
|
||||
private BlockingQueue<AuditMessage> auditMessageQueue = new LinkedBlockingQueue<>(); |
||||
|
||||
@Autowired |
||||
private List<AuditSubscriber> subscribers; |
||||
|
||||
@Autowired |
||||
private AuditConfiguration auditConfiguration; |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AuditPublishService.class); |
||||
|
||||
/** |
||||
* create a daemon thread to process the message queue |
||||
*/ |
||||
@PostConstruct |
||||
private void init() { |
||||
if (auditConfiguration.getEnabled()) { |
||||
Thread thread = new Thread(this::doPublish); |
||||
thread.setDaemon(true); |
||||
thread.setName("Audit-Log-Consume-Thread"); |
||||
thread.start(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* publish a new audit message |
||||
* |
||||
* @param message audit message |
||||
*/ |
||||
public void publish(AuditMessage message) { |
||||
if (auditConfiguration.getEnabled() && !auditMessageQueue.offer(message)) { |
||||
logger.error("add audit message failed {}", message); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* subscribers execute the message processor method |
||||
*/ |
||||
private void doPublish() { |
||||
AuditMessage message = null; |
||||
while (true) { |
||||
try { |
||||
message = auditMessageQueue.take(); |
||||
for (AuditSubscriber subscriber : subscribers) { |
||||
try { |
||||
subscriber.execute(message); |
||||
} catch (Exception e) { |
||||
logger.error("consume audit message {} failed, error detail {}", message, e); |
||||
} |
||||
} |
||||
} catch (InterruptedException e) { |
||||
logger.error("consume audit message failed {}.", message, e); |
||||
Thread.currentThread().interrupt(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,28 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.audit; |
||||
|
||||
public interface AuditSubscriber { |
||||
|
||||
/** |
||||
* process the audit message |
||||
* |
||||
* @param message |
||||
*/ |
||||
void execute(AuditMessage message); |
||||
} |
@ -0,0 +1,42 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.audit; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.AuditLog; |
||||
import org.apache.dolphinscheduler.dao.mapper.AuditLogMapper; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
public class AuditSubscriberImpl implements AuditSubscriber { |
||||
|
||||
@Autowired |
||||
private AuditLogMapper logMapper; |
||||
|
||||
@Override |
||||
public void execute(AuditMessage message) { |
||||
AuditLog auditLog = new AuditLog(); |
||||
auditLog.setUserId(message.getUser().getId()); |
||||
auditLog.setResourceType(message.getResourceType().getCode()); |
||||
auditLog.setOperation(message.getOperation().getCode()); |
||||
auditLog.setTime(message.getAuditDate()); |
||||
auditLog.setResourceId(message.getResourceId()); |
||||
logMapper.insert(auditLog); |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.configuration; |
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
@EnableConfigurationProperties |
||||
@ConfigurationProperties(value = "audit", ignoreUnknownFields = false) |
||||
public class AuditConfiguration { |
||||
private boolean enabled; |
||||
|
||||
public boolean getEnabled() { |
||||
return enabled; |
||||
} |
||||
|
||||
public void setEnabled(boolean enabled) { |
||||
this.enabled = enabled; |
||||
} |
||||
} |
@ -0,0 +1,98 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.controller; |
||||
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_AUDIT_LOG_LIST_PAGING; |
||||
|
||||
import org.apache.dolphinscheduler.api.aspect.AccessLogAnnotation; |
||||
import org.apache.dolphinscheduler.api.exceptions.ApiException; |
||||
import org.apache.dolphinscheduler.api.service.AuditService; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.AuditOperationType; |
||||
import org.apache.dolphinscheduler.common.enums.AuditResourceType; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.http.HttpStatus; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestAttribute; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RequestParam; |
||||
import org.springframework.web.bind.annotation.ResponseStatus; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import io.swagger.annotations.Api; |
||||
import io.swagger.annotations.ApiImplicitParam; |
||||
import io.swagger.annotations.ApiImplicitParams; |
||||
import io.swagger.annotations.ApiOperation; |
||||
import springfox.documentation.annotations.ApiIgnore; |
||||
|
||||
@Api(tags = "AUDIT_LOG_TAG") |
||||
@RestController |
||||
@RequestMapping("projects/audit") |
||||
public class AuditLogController extends BaseController { |
||||
|
||||
@Autowired |
||||
AuditService auditService; |
||||
|
||||
/** |
||||
* query audit log list paging |
||||
* |
||||
* @param loginUser login user |
||||
* @param pageNo page number |
||||
* @param moduleType module type |
||||
* @param operationType operation type |
||||
* @param startDate start time |
||||
* @param endDate end time |
||||
* @param userName user name |
||||
* @param pageSize page size |
||||
* @return audit log content |
||||
*/ |
||||
@ApiOperation(value = "queryAuditLogListPaging", notes = "QUERY_AUDIT_LOG") |
||||
@ApiImplicitParams({ |
||||
@ApiImplicitParam(name = "startDate", value = "START_DATE", type = "String"), |
||||
@ApiImplicitParam(name = "endDate", value = "END_DATE", type = "String"), |
||||
@ApiImplicitParam(name = "moduleType", value = "MODULE_TYPE", type = "String"), |
||||
@ApiImplicitParam(name = "operationType", value = "OPERATION_TYPE", type = "String"), |
||||
@ApiImplicitParam(name = "userName", value = "USER_NAME", type = "String"), |
||||
@ApiImplicitParam(name = "projectName", value = "PROJECT_NAME", type = "String"), |
||||
@ApiImplicitParam(name = "processName", value = "PROCESS_NAME", type = "String"), |
||||
@ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "1"), |
||||
@ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "20") |
||||
}) |
||||
@GetMapping(value = "/audit-log-list") |
||||
@ResponseStatus(HttpStatus.OK) |
||||
@ApiException(QUERY_AUDIT_LOG_LIST_PAGING) |
||||
@AccessLogAnnotation(ignoreRequestArgs = "loginUser") |
||||
public Result queryAuditLogListPaging(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, |
||||
@RequestParam("pageNo") Integer pageNo, |
||||
@RequestParam("pageSize") Integer pageSize, |
||||
@RequestParam(value = "resourceType", required = false) AuditResourceType resourceType, |
||||
@RequestParam(value = "operationType", required = false) AuditOperationType operationType, |
||||
@RequestParam(value = "startDate", required = false) String startDate, |
||||
@RequestParam(value = "endDate", required = false) String endDate, |
||||
@RequestParam(value = "userName", required = false) String userName) { |
||||
Result result = checkPageParams(pageNo, pageSize); |
||||
if (!result.checkResult()) { |
||||
return result; |
||||
} |
||||
result = auditService.queryLogListPaging(loginUser, resourceType, operationType, startDate, endDate, userName, pageNo, pageSize); |
||||
return result; |
||||
} |
||||
} |
@ -0,0 +1,76 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.dto; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
||||
public class AuditDto { |
||||
|
||||
private String userName; |
||||
|
||||
private String resource; |
||||
|
||||
private String operation; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
||||
private Date time; |
||||
|
||||
private String resourceName; |
||||
|
||||
public String getUserName() { |
||||
return userName; |
||||
} |
||||
|
||||
public void setUserName(String userName) { |
||||
this.userName = userName; |
||||
} |
||||
|
||||
public String getResource() { |
||||
return resource; |
||||
} |
||||
|
||||
public void setResource(String resource) { |
||||
this.resource = resource; |
||||
} |
||||
|
||||
public String getOperation() { |
||||
return operation; |
||||
} |
||||
|
||||
public void setOperation(String operation) { |
||||
this.operation = operation; |
||||
} |
||||
|
||||
public Date getTime() { |
||||
return time; |
||||
} |
||||
|
||||
public void setTime(Date time) { |
||||
this.time = time; |
||||
} |
||||
|
||||
public String getResourceName() { |
||||
return resourceName; |
||||
} |
||||
|
||||
public void setResourceName(String resourceName) { |
||||
this.resourceName = resourceName; |
||||
} |
||||
} |
@ -0,0 +1,57 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.service; |
||||
|
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.enums.AuditOperationType; |
||||
import org.apache.dolphinscheduler.common.enums.AuditResourceType; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
|
||||
/** |
||||
* audit information service |
||||
*/ |
||||
public interface AuditService { |
||||
|
||||
/** |
||||
* add new audit record |
||||
* |
||||
* @param user login user |
||||
* @param resourceType resource type |
||||
* @param resourceId resource id |
||||
* @param operation operation type |
||||
*/ |
||||
void addAudit(User user, AuditResourceType resourceType, Integer resourceId, AuditOperationType operation); |
||||
|
||||
/** |
||||
* query audit log list |
||||
* |
||||
* @param loginUser login user |
||||
* @param resourceType resource type |
||||
* @param operationType operation type |
||||
* @param startTime start time |
||||
* @param endTime end time |
||||
* @param userName query user name |
||||
* @param pageNo page number |
||||
* @param pageSize page size |
||||
* @return audit log string |
||||
*/ |
||||
Result queryLogListPaging(User loginUser, AuditResourceType resourceType, |
||||
AuditOperationType operationType, String startTime, |
||||
String endTime, String userName, |
||||
Integer pageNo, Integer pageSize); |
||||
} |
@ -0,0 +1,137 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.service.impl; |
||||
|
||||
import org.apache.dolphinscheduler.api.audit.AuditMessage; |
||||
import org.apache.dolphinscheduler.api.audit.AuditPublishService; |
||||
import org.apache.dolphinscheduler.api.dto.AuditDto; |
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.service.AuditService; |
||||
import org.apache.dolphinscheduler.api.utils.PageInfo; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.Constants; |
||||
import org.apache.dolphinscheduler.common.enums.AuditOperationType; |
||||
import org.apache.dolphinscheduler.common.enums.AuditResourceType; |
||||
import org.apache.dolphinscheduler.dao.entity.AuditLog; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
import org.apache.dolphinscheduler.dao.mapper.AuditLogMapper; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.stream.Collectors; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
||||
@Service |
||||
public class AuditServiceImpl extends BaseServiceImpl implements AuditService { |
||||
|
||||
@Autowired |
||||
private AuditLogMapper auditLogMapper; |
||||
|
||||
@Autowired |
||||
private AuditPublishService publishService; |
||||
|
||||
/** |
||||
* add new audit log |
||||
* |
||||
* @param user login user |
||||
* @param resourceType resource type |
||||
* @param resourceId resource id |
||||
* @param operation operation type |
||||
*/ |
||||
@Override |
||||
public void addAudit(User user, AuditResourceType resourceType, Integer resourceId, AuditOperationType operation) { |
||||
publishService.publish(new AuditMessage(user, new Date(), resourceType, operation, resourceId)); |
||||
} |
||||
|
||||
/** |
||||
* query audit log paging |
||||
* |
||||
* @param loginUser login user |
||||
* @param resourceType resource type |
||||
* @param operationType operation type |
||||
* @param startDate start time |
||||
* @param endDate end time |
||||
* @param userName query user name |
||||
* @param pageNo page number |
||||
* @param pageSize page size |
||||
* @return audit log string data |
||||
*/ |
||||
@Override |
||||
public Result queryLogListPaging(User loginUser, AuditResourceType resourceType, |
||||
AuditOperationType operationType, String startDate, |
||||
String endDate, String userName, |
||||
Integer pageNo, Integer pageSize) { |
||||
Result result = new Result(); |
||||
|
||||
Map<String, Object> checkAndParseDateResult = checkAndParseDateParameters(startDate, endDate); |
||||
Status resultEnum = (Status) checkAndParseDateResult.get(Constants.STATUS); |
||||
if (resultEnum != Status.SUCCESS) { |
||||
putMsg(result,resultEnum); |
||||
return result; |
||||
} |
||||
|
||||
int[] resourceArray = null; |
||||
if (resourceType != null) { |
||||
resourceArray = new int[]{resourceType.getCode()}; |
||||
} |
||||
|
||||
int[] opsArray = null; |
||||
if (operationType != null) { |
||||
opsArray = new int[]{operationType.getCode()}; |
||||
} |
||||
|
||||
Date start = (Date) checkAndParseDateResult.get(Constants.START_TIME); |
||||
Date end = (Date) checkAndParseDateResult.get(Constants.END_TIME); |
||||
|
||||
Page<AuditLog> page = new Page<>(pageNo, pageSize); |
||||
IPage<AuditLog> logIPage = auditLogMapper.queryAuditLog(page, resourceArray, opsArray, userName, start, end); |
||||
List<AuditLog> logList = logIPage != null ? logIPage.getRecords() : new ArrayList<>(); |
||||
PageInfo<AuditDto> pageInfo = new PageInfo<>(pageNo, pageSize); |
||||
|
||||
List<AuditDto> auditDtos = logList.stream().map(this::transformAuditLog).collect(Collectors.toList()); |
||||
pageInfo.setTotal((int) (auditDtos != null ? auditDtos.size() : 0L)); |
||||
pageInfo.setTotalList(auditDtos); |
||||
result.setData(pageInfo); |
||||
putMsg(result, Status.SUCCESS); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* transform AuditLog to AuditDto |
||||
* |
||||
* @param auditLog audit log |
||||
* @return audit dto |
||||
*/ |
||||
private AuditDto transformAuditLog(AuditLog auditLog) { |
||||
AuditDto auditDto = new AuditDto(); |
||||
String resourceType = AuditResourceType.of(auditLog.getResourceType()).getMsg(); |
||||
auditDto.setResource(resourceType); |
||||
auditDto.setOperation(AuditOperationType.of(auditLog.getOperation()).getMsg()); |
||||
auditDto.setUserName(auditLog.getUserName()); |
||||
auditDto.setResourceName(auditLogMapper.queryResourceNameByType(resourceType, auditLog.getResourceId())); |
||||
auditDto.setTime(auditLog.getTime()); |
||||
return auditDto; |
||||
} |
||||
} |
@ -0,0 +1,49 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.audit; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.AuditOperationType; |
||||
import org.apache.dolphinscheduler.common.enums.AuditResourceType; |
||||
import org.apache.dolphinscheduler.dao.entity.AuditLog; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
import org.apache.dolphinscheduler.dao.mapper.AuditLogMapper; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.InjectMocks; |
||||
import org.mockito.Mock; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
|
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class AuditSubscriberTest { |
||||
|
||||
@Mock |
||||
private AuditLogMapper logMapper; |
||||
|
||||
@InjectMocks |
||||
private AuditSubscriberImpl auditSubscriber; |
||||
|
||||
@Test |
||||
public void testExecute() { |
||||
Mockito.when(logMapper.insert(Mockito.any(AuditLog.class))).thenReturn(1); |
||||
auditSubscriber.execute(new AuditMessage(new User(), new Date(), AuditResourceType.USER_MODULE, AuditOperationType.CREATE, 1)); |
||||
} |
||||
} |
@ -0,0 +1,40 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.configuration; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.test.context.ActiveProfiles; |
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
||||
|
||||
@ActiveProfiles("audit") |
||||
@RunWith(SpringJUnit4ClassRunner.class) |
||||
@SpringBootTest(classes = AuditConfiguration.class) |
||||
public class AuditConfigurationTest { |
||||
|
||||
@Autowired |
||||
private AuditConfiguration auditConfiguration; |
||||
|
||||
@Test |
||||
public void isAuditGlobalControlSwitch() { |
||||
Assert.assertTrue(auditConfiguration.getEnabled()); |
||||
} |
||||
} |
@ -0,0 +1,61 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.controller; |
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; |
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.test.web.servlet.MvcResult; |
||||
import org.springframework.util.LinkedMultiValueMap; |
||||
import org.springframework.util.MultiValueMap; |
||||
|
||||
/** |
||||
* audit log controller test |
||||
*/ |
||||
public class AuditLogControllerTest extends AbstractControllerTest { |
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(AuditLogControllerTest.class); |
||||
|
||||
@Test |
||||
public void testQueryAuditLogListPaging() throws Exception { |
||||
MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>(); |
||||
paramsMap.add("pageNo", "1"); |
||||
paramsMap.add("pageSize", "10"); |
||||
|
||||
MvcResult mvcResult = mockMvc.perform(get("/projects/audit/audit-log-list") |
||||
.header(SESSION_ID, sessionId) |
||||
.params(paramsMap)) |
||||
.andExpect(status().isOk()) |
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) |
||||
.andReturn(); |
||||
|
||||
Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); |
||||
Assert.assertEquals(Status.SUCCESS.getCode(),result.getCode().intValue()); |
||||
logger.info(mvcResult.getResponse().getContentAsString()); |
||||
} |
||||
} |
@ -0,0 +1,91 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.service; |
||||
|
||||
import static org.mockito.ArgumentMatchers.eq; |
||||
import static org.mockito.Mockito.when; |
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status; |
||||
import org.apache.dolphinscheduler.api.service.impl.AuditServiceImpl; |
||||
import org.apache.dolphinscheduler.api.utils.Result; |
||||
import org.apache.dolphinscheduler.common.utils.DateUtils; |
||||
import org.apache.dolphinscheduler.dao.entity.AuditLog; |
||||
import org.apache.dolphinscheduler.dao.entity.User; |
||||
import org.apache.dolphinscheduler.dao.mapper.AuditLogMapper; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.InjectMocks; |
||||
import org.mockito.Mock; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
||||
/** |
||||
* audit service test |
||||
*/ |
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class AuditServiceTest { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AuditServiceTest.class); |
||||
|
||||
@InjectMocks |
||||
private AuditServiceImpl auditService; |
||||
|
||||
@Mock |
||||
private AuditLogMapper auditLogMapper; |
||||
|
||||
@Test |
||||
public void testQueryLogListPaging() { |
||||
Date start = DateUtils.getScheduleDate("2020-11-01 00:00:00"); |
||||
Date end = DateUtils.getScheduleDate("2020-11-02 00:00:00"); |
||||
|
||||
IPage<AuditLog> page = new Page<>(1, 10); |
||||
page.setRecords(getLists()); |
||||
page.setTotal(1L); |
||||
when(auditLogMapper.queryAuditLog(Mockito.any(Page.class), Mockito.any(), Mockito.any(), |
||||
Mockito.eq(""), eq(start), eq(end))) |
||||
.thenReturn(page); |
||||
Result result = auditService.queryLogListPaging(new User(), null, null, "2020-11-01 00:00:00", "2020-11-02 00:00:00", "", 1, 10); |
||||
logger.info(result.toString()); |
||||
Assert.assertEquals(Status.SUCCESS.getCode(), (int) result.getCode()); |
||||
} |
||||
|
||||
private List<AuditLog> getLists() { |
||||
List<AuditLog> list = new ArrayList<>(); |
||||
list.add(getAuditLog()); |
||||
return list; |
||||
} |
||||
|
||||
private AuditLog getAuditLog() { |
||||
AuditLog auditLog = new AuditLog(); |
||||
auditLog.setUserName("testName"); |
||||
auditLog.setOperation(0); |
||||
auditLog.setResourceType(0); |
||||
return auditLog; |
||||
} |
||||
} |
@ -0,0 +1,62 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.common.enums; |
||||
|
||||
import java.util.HashMap; |
||||
|
||||
/** |
||||
* Audit Operation type |
||||
*/ |
||||
public enum AuditOperationType { |
||||
|
||||
CREATE(0, "CREATE"), |
||||
READ(1, "READ"), |
||||
UPDATE(2, "UPDATE"), |
||||
DELETE(3, "DELETE"); |
||||
|
||||
private final int code; |
||||
private final String enMsg; |
||||
|
||||
private static HashMap<Integer, AuditOperationType> AUDIT_OPERATION_MAP = new HashMap<>(); |
||||
|
||||
static { |
||||
for (AuditOperationType operationType : AuditOperationType.values()) { |
||||
AUDIT_OPERATION_MAP.put(operationType.code, operationType); |
||||
} |
||||
} |
||||
|
||||
AuditOperationType(int code, String enMsg) { |
||||
this.code = code; |
||||
this.enMsg = enMsg; |
||||
} |
||||
|
||||
public static AuditOperationType of(int status) { |
||||
if (AUDIT_OPERATION_MAP.containsKey(status)) { |
||||
return AUDIT_OPERATION_MAP.get(status); |
||||
} |
||||
throw new IllegalArgumentException("invalid audit operation type code " + status); |
||||
} |
||||
|
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public String getMsg() { |
||||
return enMsg; |
||||
} |
||||
} |
@ -0,0 +1,60 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.common.enums; |
||||
|
||||
import java.util.HashMap; |
||||
|
||||
/** |
||||
* Audit Module type |
||||
*/ |
||||
public enum AuditResourceType { |
||||
// TODO: add other audit resource enums
|
||||
USER_MODULE(0, "USER"), |
||||
PROJECT_MODULE(1, "PROJECT"); |
||||
|
||||
private final int code; |
||||
private final String enMsg; |
||||
|
||||
private static HashMap<Integer, AuditResourceType> AUDIT_RESOURCE_MAP = new HashMap<>(); |
||||
|
||||
static { |
||||
for (AuditResourceType auditResourceType : AuditResourceType.values()) { |
||||
AUDIT_RESOURCE_MAP.put(auditResourceType.code, auditResourceType); |
||||
} |
||||
} |
||||
|
||||
AuditResourceType(int code, String enMsg) { |
||||
this.code = code; |
||||
this.enMsg = enMsg; |
||||
} |
||||
|
||||
public int getCode() { |
||||
return this.code; |
||||
} |
||||
|
||||
public String getMsg() { |
||||
return this.enMsg; |
||||
} |
||||
|
||||
public static AuditResourceType of(int status) { |
||||
if (AUDIT_RESOURCE_MAP.containsKey(status)) { |
||||
return AUDIT_RESOURCE_MAP.get(status); |
||||
} |
||||
throw new IllegalArgumentException("invalid audit resource type code " + status); |
||||
} |
||||
} |
@ -0,0 +1,116 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.dao.entity; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
||||
@TableName("t_ds_audit_log") |
||||
public class AuditLog { |
||||
|
||||
/** |
||||
* id |
||||
*/ |
||||
@TableId(value = "id", type = IdType.AUTO) |
||||
private int id; |
||||
|
||||
/** |
||||
* user id |
||||
*/ |
||||
private Integer userId; |
||||
|
||||
/** |
||||
* resource type |
||||
*/ |
||||
private Integer resourceType; |
||||
|
||||
/** |
||||
* operation type |
||||
*/ |
||||
private Integer operation; |
||||
|
||||
/** |
||||
* resource id |
||||
*/ |
||||
private Integer resourceId; |
||||
|
||||
/** |
||||
* user name |
||||
*/ |
||||
@TableField(exist = false) |
||||
private String userName; |
||||
|
||||
/** |
||||
* operation time |
||||
*/ |
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
||||
private Date time; |
||||
|
||||
public Integer getUserId() { |
||||
return userId; |
||||
} |
||||
|
||||
public void setUserId(Integer userId) { |
||||
this.userId = userId; |
||||
} |
||||
|
||||
public Integer getResourceType() { |
||||
return resourceType; |
||||
} |
||||
|
||||
public void setResourceType(Integer resourceType) { |
||||
this.resourceType = resourceType; |
||||
} |
||||
|
||||
public Integer getOperation() { |
||||
return operation; |
||||
} |
||||
|
||||
public void setOperation(Integer operation) { |
||||
this.operation = operation; |
||||
} |
||||
|
||||
public Integer getResourceId() { |
||||
return resourceId; |
||||
} |
||||
|
||||
public void setResourceId(Integer resourceId) { |
||||
this.resourceId = resourceId; |
||||
} |
||||
|
||||
public String getUserName() { |
||||
return userName; |
||||
} |
||||
|
||||
public void setUserName(String userName) { |
||||
this.userName = userName; |
||||
} |
||||
|
||||
public Date getTime() { |
||||
return time; |
||||
} |
||||
|
||||
public void setTime(Date time) { |
||||
this.time = time; |
||||
} |
||||
} |
@ -0,0 +1,42 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.dao.mapper; |
||||
|
||||
import org.apache.dolphinscheduler.dao.entity.AuditLog; |
||||
|
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
|
||||
/** |
||||
* auditlog mapper interface
|
||||
*/ |
||||
public interface AuditLogMapper extends BaseMapper<AuditLog> { |
||||
IPage<AuditLog> queryAuditLog(IPage<AuditLog> page, |
||||
@Param("resourceType") int[] resourceArray, |
||||
@Param("operationType") int[] operationType, |
||||
@Param("userName") String userName, |
||||
@Param("startDate") Date startDate, |
||||
@Param("endDate") Date endDate); |
||||
|
||||
String queryResourceNameByType(@Param("resourceType") String resourceType, |
||||
@Param("resourceId") Integer resourceId); |
||||
} |
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?> |
||||
<!-- |
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||
~ contributor license agreements. See the NOTICE file distributed with |
||||
~ this work for additional information regarding copyright ownership. |
||||
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
~ (the "License"); you may not use this file except in compliance with |
||||
~ the License. You may obtain a copy of the License at |
||||
~ |
||||
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||
~ |
||||
~ Unless required by applicable law or agreed to in writing, software |
||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
~ See the License for the specific language governing permissions and |
||||
~ limitations under the License. |
||||
--> |
||||
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > |
||||
<mapper namespace="org.apache.dolphinscheduler.dao.mapper.AuditLogMapper"> |
||||
<sql id="baseSql"> |
||||
id, user_id, resource_type, operation, resource_id, time |
||||
</sql> |
||||
<sql id="baseSqlV2"> |
||||
${alias}.id, ${alias}.user_id, ${alias}.resource_type, ${alias}.operation, ${alias}.resource_id, ${alias}.time |
||||
</sql> |
||||
|
||||
<select id="queryAuditLog" resultType="org.apache.dolphinscheduler.dao.entity.AuditLog"> |
||||
select |
||||
<include refid="baseSqlV2"> |
||||
<property name="alias" value="log"/> |
||||
</include> |
||||
, |
||||
u.user_name as user_name |
||||
from t_ds_audit_log log |
||||
join t_ds_user u on log.user_id = u.id |
||||
where 1 = 1 |
||||
<if test="startDate != null"> |
||||
and log.time > #{startDate} and log.time <![CDATA[ <=]]> #{endDate} |
||||
</if> |
||||
<if test="resourceType != null and resourceType.length > 0"> |
||||
and log.resource_type in |
||||
<foreach collection="resourceType" index="index" item="i" open="(" separator="," close=")"> |
||||
#{i} |
||||
</foreach> |
||||
</if> |
||||
<if test="operationType != null and operationType.length > 0"> |
||||
and log.operation in |
||||
<foreach collection="operationType" index="index" item="j" open="(" separator="," close=")"> |
||||
#{j} |
||||
</foreach> |
||||
</if> |
||||
<if test="userName != null and userName != ''"> |
||||
and u.user_name = #{userName} |
||||
</if> |
||||
order by log.time desc |
||||
</select> |
||||
|
||||
<select id="queryResourceNameByType" resultType="String"> |
||||
<if test="resourceType != null and resourceType == 'USER'"> |
||||
select user_name from t_ds_user where id = #{resourceId} |
||||
</if> |
||||
</select> |
||||
</mapper> |
@ -0,0 +1,70 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.dao.mapper; |
||||
|
||||
import org.apache.dolphinscheduler.dao.BaseDaoTest; |
||||
import org.apache.dolphinscheduler.dao.entity.AuditLog; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
||||
public class AuditLogMapperTest extends BaseDaoTest { |
||||
|
||||
@Autowired |
||||
AuditLogMapper logMapper; |
||||
|
||||
/** |
||||
* insert |
||||
* @return |
||||
*/ |
||||
private void insertOne() { |
||||
AuditLog auditLog = new AuditLog(); |
||||
auditLog.setUserId(1); |
||||
auditLog.setTime(new Date()); |
||||
auditLog.setResourceType(0); |
||||
auditLog.setOperation(0); |
||||
auditLog.setResourceId(0); |
||||
logMapper.insert(auditLog); |
||||
} |
||||
|
||||
/** |
||||
* test page query |
||||
*/ |
||||
@Test |
||||
public void testQueryAuditLog() { |
||||
insertOne(); |
||||
Page<AuditLog> page = new Page<>(1, 3); |
||||
int[] resourceType = new int[0]; |
||||
int[] operationType = new int[0]; |
||||
|
||||
IPage<AuditLog> logIPage = logMapper.queryAuditLog(page, resourceType, operationType, "", null, null); |
||||
Assert.assertNotEquals(logIPage.getTotal(), 0); |
||||
} |
||||
|
||||
@Test |
||||
public void testQueryResourceNameByType() { |
||||
String resourceName = logMapper.queryResourceNameByType("USER", 1); |
||||
Assert.assertEquals("admin", resourceName); |
||||
} |
||||
} |
@ -0,0 +1,127 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
<template> |
||||
<m-conditions> |
||||
<template slot="search-group"> |
||||
<div class="list"> |
||||
<el-button size="mini" @click="_ckQuery" icon="el-icon-search"></el-button> |
||||
</div> |
||||
<div class="list"> |
||||
<el-date-picker |
||||
style="width: 310px" |
||||
v-model="dataTime" |
||||
size="mini" |
||||
@change="_onChangeStartStop" |
||||
type="datetimerange" |
||||
range-separator="-" |
||||
:start-placeholder="$t('startDate')" |
||||
:end-placeholder="$t('endDate')" |
||||
value-format="yyyy-MM-dd HH:mm:ss"> |
||||
</el-date-picker> |
||||
</div> |
||||
<div class="list"> |
||||
<el-select style="width: 140px;" @change="_onChangeResource" :value="searchParams.resourceType" :placeholder="$t('Resource Type')" size="mini"> |
||||
<el-option |
||||
v-for="module in resourceTypeList" |
||||
:key="module.label" |
||||
:value="module.code" |
||||
:label="module.label"> |
||||
</el-option> |
||||
</el-select> |
||||
</div> |
||||
<div class="list"> |
||||
<el-select style="width: 140px;" @change="_onChangeOperation" :value="searchParams.operationType" :placeholder="$t('Operation')" size="mini"> |
||||
<el-option |
||||
v-for="operation in operationTypeList" |
||||
:key="operation.label" |
||||
:value="operation.code" |
||||
:label="operation.label"> |
||||
</el-option> |
||||
</el-select> |
||||
</div> |
||||
<div class="list"> |
||||
<el-input v-model="searchParams.userName" @keyup.enter.native="_ckQuery" style="width: 140px;" size="mini" :placeholder="$t('User Name')"></el-input> |
||||
</div> |
||||
</template> |
||||
</m-conditions> |
||||
</template> |
||||
<script> |
||||
import _ from 'lodash' |
||||
import { resourceType, operationType } from './common' |
||||
import mConditions from '@/module/components/conditions/conditions' |
||||
export default { |
||||
name: 'monitor-log-conditions', |
||||
data () { |
||||
return { |
||||
// state(list) |
||||
resourceTypeList: resourceType, |
||||
operationTypeList: operationType, |
||||
searchParams: { |
||||
// resource type |
||||
resourceType: '', |
||||
// operation |
||||
operationType: '', |
||||
// start date |
||||
startDate: '', |
||||
// end date |
||||
endDate: '' |
||||
}, |
||||
dataTime: [] |
||||
} |
||||
}, |
||||
props: {}, |
||||
methods: { |
||||
_ckQuery () { |
||||
this.$emit('on-query', this.searchParams) |
||||
}, |
||||
/** |
||||
* change times |
||||
*/ |
||||
_onChangeStartStop (val) { |
||||
this.searchParams.startDate = val[0] |
||||
this.searchParams.endDate = val[1] |
||||
this.dataTime[0] = val[0] |
||||
this.dataTime[1] = val[1] |
||||
}, |
||||
/** |
||||
* change resource |
||||
*/ |
||||
_onChangeResource (val) { |
||||
this.searchParams.resourceType = val |
||||
}, |
||||
/** |
||||
* change operation |
||||
*/ |
||||
_onChangeOperation (val) { |
||||
this.searchParams.operationType = val |
||||
} |
||||
}, |
||||
watch: { |
||||
}, |
||||
created () { |
||||
// Routing parameter merging |
||||
if (!_.isEmpty(this.$route.query)) { |
||||
this.searchParams = _.assign(this.searchParams, this.$route.query) |
||||
} |
||||
}, |
||||
mounted () { |
||||
}, |
||||
computed: { |
||||
}, |
||||
components: { mConditions } |
||||
} |
||||
</script> |
@ -0,0 +1,60 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
import i18n from '@/module/i18n' |
||||
|
||||
/** |
||||
* Module code table |
||||
*/ |
||||
const resourceType = [ |
||||
{ |
||||
code: '', |
||||
label: `${i18n.$t('Resource Type')}` |
||||
}, { |
||||
code: 'USER_MODULE', |
||||
label: `${i18n.$t('User Audit')}` |
||||
}, { |
||||
code: 'PROJECT_MODULE', |
||||
label: `${i18n.$t('Project Audit')}` |
||||
} |
||||
] |
||||
|
||||
/** |
||||
* Operation code table |
||||
*/ |
||||
const operationType = [ |
||||
{ |
||||
code: '', |
||||
label: `${i18n.$t('All Operations')}` |
||||
}, { |
||||
code: 'CREATE', |
||||
label: `${i18n.$t('Create Operation')}` |
||||
}, { |
||||
code: 'UPDATE', |
||||
label: `${i18n.$t('Update Operation')}` |
||||
}, { |
||||
code: 'DELETE', |
||||
label: `${i18n.$t('Delete Operation')}` |
||||
}, { |
||||
code: 'READ', |
||||
label: `${i18n.$t('Read Operation')}` |
||||
} |
||||
] |
||||
|
||||
export { |
||||
resourceType, operationType |
||||
} |
@ -0,0 +1,24 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
<template> |
||||
<router-view></router-view> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
name: 'monitor-conditions-index' |
||||
} |
||||
</script> |
@ -0,0 +1,72 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
<template> |
||||
<div class="list-model"> |
||||
<div class="table-box"> |
||||
<el-table :data="list" size="mini" style="width: 100%"> |
||||
<el-table-column type="index" :label="$t('#')" width="50"></el-table-column> |
||||
<el-table-column prop="userName" :label="$t('User Name')"></el-table-column> |
||||
<el-table-column prop="resource" :label="$t('Resource Type')"></el-table-column> |
||||
<el-table-column prop="resourceName" :label="$t('Project Name')"></el-table-column> |
||||
<el-table-column prop="operation" :label="$t('Operation')"> |
||||
<template slot-scope="scope"> |
||||
<span>{{scope.row.operation | filterNull}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column :label="$t('Create Time')" min-width="120"> |
||||
<template slot-scope="scope"> |
||||
<span>{{scope.row.time | formatDate}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
name: 'audit-list', |
||||
data () { |
||||
return { |
||||
list: [] |
||||
} |
||||
}, |
||||
props: { |
||||
logList: Array, |
||||
pageNo: Number, |
||||
pageSize: Number |
||||
}, |
||||
methods: { |
||||
_edit (item) { |
||||
this.$emit('on-edit', item) |
||||
} |
||||
}, |
||||
watch: { |
||||
logList (a) { |
||||
this.list = [] |
||||
setTimeout(() => { |
||||
this.list = a |
||||
}) |
||||
} |
||||
}, |
||||
created () { |
||||
this.list = this.logList |
||||
}, |
||||
mounted () { |
||||
}, |
||||
components: { } |
||||
} |
||||
</script> |
@ -0,0 +1,157 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
<template> |
||||
<m-list-construction :title="$t('Audit Log')"> |
||||
<template slot="conditions"> |
||||
<m-log-conditions @on-query="_onQuery"></m-log-conditions> |
||||
</template> |
||||
<template slot="content"> |
||||
<template v-if="logList.length || total>0"> |
||||
<m-list @on-edit="_onEdit" |
||||
:log-list="logList" |
||||
:page-no="searchParams.pageNo" |
||||
:page-size="searchParams.pageSize"> |
||||
</m-list> |
||||
<div class="page-box"> |
||||
<el-pagination |
||||
background |
||||
@current-change="_page" |
||||
@size-change="_pageSize" |
||||
:page-size="searchParams.pageSize" |
||||
:current-page.sync="searchParams.pageNo" |
||||
:page-sizes="[10, 30, 50]" |
||||
layout="sizes, prev, pager, next, jumper" |
||||
:total="total"> |
||||
</el-pagination> |
||||
</div> |
||||
</template> |
||||
<template v-if="!logList.length && total<=0"> |
||||
<m-no-data></m-no-data> |
||||
</template> |
||||
<m-spin :is-spin="isLoading" :is-left="isLeft"></m-spin> |
||||
</template> |
||||
</m-list-construction> |
||||
</template> |
||||
<script> |
||||
import _ from 'lodash' |
||||
import { mapActions } from 'vuex' |
||||
import mList from './_source/list' |
||||
import store from '@/conf/home/store' |
||||
import mSpin from '@/module/components/spin/spin' |
||||
import mNoData from '@/module/components/noData/noData' |
||||
import listUrlParamHandle from '@/module/mixin/listUrlParamHandle' |
||||
import mListConstruction from '@/module/components/listConstruction/listConstruction' |
||||
import mLogConditions from '@/conf/home/pages/monitor/pages/_source/conditions/audit/auditLog' |
||||
|
||||
export default { |
||||
name: 'audit-log-index', |
||||
data () { |
||||
return { |
||||
total: null, |
||||
isLoading: true, |
||||
logList: [], |
||||
searchParams: { |
||||
pageSize: 10, |
||||
pageNo: 1, |
||||
// resource type |
||||
resourceType: '', |
||||
// operation |
||||
operationType: '', |
||||
// start date |
||||
startDate: '', |
||||
// end date |
||||
endDate: '', |
||||
// operator |
||||
userName: '' |
||||
}, |
||||
isLeft: true, |
||||
// isEffective: 1, |
||||
isADMIN: store.state.user.userInfo.userType === 'ADMIN_USER', |
||||
item: {} |
||||
} |
||||
}, |
||||
mixins: [listUrlParamHandle], |
||||
props: {}, |
||||
methods: { |
||||
...mapActions('projects', ['getAuditLogList']), |
||||
/** |
||||
* click query |
||||
*/ |
||||
_onQuery (o) { |
||||
this.searchParams = _.assign(this.searchParams, o) |
||||
this.searchParams.pageNo = 1 |
||||
}, |
||||
_page (val) { |
||||
this.searchParams.pageNo = val |
||||
}, |
||||
_pageSize (val) { |
||||
this.searchParams.pageSize = val |
||||
}, |
||||
_onUpdate () { |
||||
this._debounceGET() |
||||
}, |
||||
close () { |
||||
}, |
||||
_getList (flag) { |
||||
this.isLoading = !flag |
||||
this.getAuditLogList(this.searchParams).then(res => { |
||||
if (this.searchParams.pageNo > 1 && res.totalList.length === 0) { |
||||
this.searchParams.pageNo = this.searchParams.pageNo - 1 |
||||
} else { |
||||
this.logList = [] |
||||
this.logList = res.totalList |
||||
this.total = res.total |
||||
this.isLoading = false |
||||
} |
||||
}).catch(e => { |
||||
this.isLoading = false |
||||
}) |
||||
}, |
||||
_debounceGET: _.debounce(function (flag) { |
||||
if (Number(sessionStorage.getItem('isLeft')) === 0) { |
||||
this.isLeft = false |
||||
} else { |
||||
this.isLeft = true |
||||
} |
||||
this._getList(flag) |
||||
}, 100, { |
||||
leading: false, |
||||
trailing: true |
||||
}) |
||||
}, |
||||
watch: { |
||||
// router |
||||
'$route' (a) { |
||||
// url no params get instance list |
||||
this.searchParams.pageNo = _.isEmpty(a.query) ? 1 : a.query.pageNo |
||||
} |
||||
}, |
||||
created () { |
||||
}, |
||||
mounted () { |
||||
// Cycle acquisition status |
||||
this.setIntervalP = setInterval(() => { |
||||
this._debounceGET('false') |
||||
}, 90000) |
||||
}, |
||||
beforeDestroy () { |
||||
clearInterval(this.setIntervalP) |
||||
sessionStorage.setItem('isLeft', 1) |
||||
}, |
||||
components: { mList, mListConstruction, mSpin, mNoData, mLogConditions } |
||||
} |
||||
</script> |
Loading…
Reference in new issue