package com.denimgroup.threadfix.webapp.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import com.denimgroup.threadfix.data.entities.Application;
import com.denimgroup.threadfix.data.entities.Defect;
import com.denimgroup.threadfix.data.entities.Permission;
import com.denimgroup.threadfix.data.entities.Vulnerability;
import com.denimgroup.threadfix.service.ApplicationService;
import com.denimgroup.threadfix.service.PermissionService;
import com.denimgroup.threadfix.service.SanitizedLogger;
import com.denimgroup.threadfix.service.VulnerabilityService;
import com.denimgroup.threadfix.webapp.viewmodels.VulnerabilityCollectionModel;
@Controller
@RequestMapping("/organizations/{orgId}/applications/{appId}")
@SessionAttributes({"defectTracker", "application", "waf", "defectViewModel"})
public class VulnerabilityTabController {
private final SanitizedLogger log = new SanitizedLogger(VulnerabilityTabController.class);
private ApplicationService applicationService;
private PermissionService permissionService;
private VulnerabilityService vulnerabilityService;
public VulnerabilityTabController(){}
@Autowired
public VulnerabilityTabController(ApplicationService applicationService,
VulnerabilityService vulnerabilityService,
PermissionService permissionService) {
this.applicationService = applicationService;
this.permissionService = permissionService;
this.vulnerabilityService = vulnerabilityService;
}
////////////////////////////////////////////////////
// Tab Methods
////////////////////////////////////////////////////
@RequestMapping(value="/vulnTab", method = RequestMethod.GET)
public String vulnTab(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
Model model) {
if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) {
return "403";
}
Application application = applicationService.loadApplication(appId);
if (application == null || !application.isActive()) {
log.warn(ResourceNotFoundException.getLogMessage("Application", appId));
throw new ResourceNotFoundException();
}
long numVulns = applicationService.getVulnCount(appId, true);
long numClosedVulns = applicationService.getVulnCount(appId, false);
model.addAttribute("numVulns", numVulns);
model.addAttribute("numClosedVulns", numClosedVulns);
model.addAttribute(application);
model.addAttribute("contentPage", "applications/tabs/vulnTab.jsp");
permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES);
return "ajaxSuccessHarness";
}
@RequestMapping(value="/scanTab", method = RequestMethod.GET)
public String scanTab(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
Model model) {
if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) {
return "403";
}
Application application = applicationService.loadApplication(appId);
if (application == null || !application.isActive()) {
log.warn(ResourceNotFoundException.getLogMessage("Application", appId));
throw new ResourceNotFoundException();
}
model.addAttribute(application);
permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES,
Permission.CAN_UPLOAD_SCANS);
model.addAttribute("contentPage", "applications/tabs/scanTab.jsp");
return "ajaxSuccessHarness";
}
@RequestMapping(value="/closedTab", method = RequestMethod.GET)
public String closedTab(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
Model model) {
if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) {
return "403";
}
Application application = applicationService.loadApplication(appId);
if (application == null || !application.isActive()) {
log.warn(ResourceNotFoundException.getLogMessage("Application", appId));
throw new ResourceNotFoundException();
}
TableSortBean basicBean = new TableSortBean();
basicBean.setOpen(false);
long numVulns = applicationService.getCount(appId, basicBean);
model.addAttribute("numVulns", numVulns);
model.addAttribute(application);
permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES);
model.addAttribute("contentPage", "applications/tabs/closedTab.jsp");
return "ajaxSuccessHarness";
}
@RequestMapping(value="/falsePositiveTab", method = RequestMethod.GET)
public String falsePositiveTab(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
Model model) {
if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) {
return "403";
}
permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES);
model.addAttribute("contentPage", "applications/tabs/falsePositiveTab.jsp");
return "ajaxSuccessHarness";
}
////////////////////////////////////////////////////
// Table Methods
////////////////////////////////////////////////////
@RequestMapping(value="/table", method = RequestMethod.POST)
public String getOpenTableVulns(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
@RequestBody TableSortBean bean,
Model model) {
bean.setOpen(true);
bean.setFalsePositive(false);
return table(orgId, appId, bean, model);
}
@RequestMapping(value="/closedVulnerabilities/table", method = RequestMethod.POST)
public String getClosedTableVulns(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
@RequestBody TableSortBean bean,
Model model) {
bean.setOpen(false);
bean.setFalsePositive(false);
return table(orgId, appId, bean, model);
}
@RequestMapping(value="/falsePositives/table", method = RequestMethod.POST)
public String markTableVulnsFalsePositive(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
@RequestBody TableSortBean bean,
Model model) {
bean.setOpen(false);
bean.setFalsePositive(true);
return table(orgId, appId, bean, model);
}
public String table(int orgId, int appId, TableSortBean bean, Model model) {
if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) {
return "403";
}
Application application = applicationService.loadApplication(appId);
if (application == null || !application.isActive()) {
log.warn(ResourceNotFoundException.getLogMessage("Application", appId));
throw new ResourceNotFoundException();
}
long numVulns = applicationService.getCount(appId, bean);
long numPages = (numVulns / 100);
if (numVulns % 100 == 0) {
numPages -= 1;
}
model.addAttribute("numPages", numPages);
model.addAttribute("numVulns", numVulns);
if (bean.getPage() > numPages) {
bean.setPage((int) (numPages + 1));
}
if (bean.getPage() < 1) {
bean.setPage(1);
}
List<Vulnerability> vulnList = applicationService.getVulnTable(appId, bean);
model.addAttribute("vulnerabilityGroups", VulnerabilityGroup.generateGroups(vulnList, bean.isDefaultBean()));
model.addAttribute("ages", vulnerabilityService.getAges(vulnList));
model.addAttribute("page", bean.getPage());
model.addAttribute("openCodes", Defect.OPEN_CODES);
model.addAttribute("closedCodes", Defect.CLOSED_CODES);
model.addAttribute(application);
permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES, Permission.CAN_SUBMIT_DEFECTS);
return "applications/vulnTable";
}
@RequestMapping(value="/table/close", method = RequestMethod.POST)
public String closeTableVulnList(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
@ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel,
Model model, HttpServletRequest request) {
if (!checkCollectionModel(vulnerabilityCollectionModel, model)) {
return "ajaxFailureHarness";
}
vulnerabilityService.closeAll(
vulnerabilityCollectionModel.getVulnerabilityIds());
String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds());
ControllerUtils.addSuccessMessage(request, start + "been closed successfully.");
return redirectToApp(model, orgId, appId);
}
@RequestMapping(value="/table/open", method = RequestMethod.POST)
public String openTableVulnList(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
@ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel,
Model model, HttpServletRequest request) {
if (!checkCollectionModel(vulnerabilityCollectionModel, model)) {
return "ajaxFailureHarness";
}
vulnerabilityService.openAll(
vulnerabilityCollectionModel.getVulnerabilityIds());
String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds());
ControllerUtils.addSuccessMessage(request, start + "been opened successfully.");
return redirectToApp(model, orgId, appId);
}
@RequestMapping(value="/falsePositives/mark", method = RequestMethod.POST)
public String setVulnsFalsePositive(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
@ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel,
Model model, HttpServletRequest request) {
if (!checkCollectionModel(vulnerabilityCollectionModel, model)) {
return "ajaxFailureHarness";
}
vulnerabilityService.markListAsFalsePositive(vulnerabilityCollectionModel
.getVulnerabilityIds());
String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds());
ControllerUtils.addSuccessMessage(request, start + "been marked successfully as false positives.");
return redirectToApp(model, orgId, appId);
}
@RequestMapping(value="/falsePositives/unmark", method = RequestMethod.POST)
public String setVulnsNotFalsePositive(@PathVariable("orgId") Integer orgId,
@PathVariable("appId") Integer appId,
@ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel,
Model model, HttpServletRequest request) {
if (!checkCollectionModel(vulnerabilityCollectionModel, model)) {
return "ajaxFailureHarness";
}
vulnerabilityService.markListAsNotFalsePositive(vulnerabilityCollectionModel
.getVulnerabilityIds());
String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds());
ControllerUtils.addSuccessMessage(request, start + "been unmarked successfully.");
return redirectToApp(model, orgId, appId);
}
private String redirectToApp(Model model, int orgId, int appId) {
model.addAttribute("contentPage", "/organizations/" + orgId + "/applications/" + appId);
return "ajaxRedirectHarness";
}
private boolean checkCollectionModel(VulnerabilityCollectionModel vulnerabilityCollectionModel,
Model model) {
if (vulnerabilityCollectionModel == null
|| vulnerabilityCollectionModel.getVulnerabilityIds() == null
|| vulnerabilityCollectionModel.getVulnerabilityIds().size() == 0) {
String error = "You must select at least one vulnerability.";
model.addAttribute("errorMessage", error);
model.addAttribute("contentPage", "errorMessage.jsp");
return false;
} else {
return true;
}
}
private String getMessageStart(List<Integer> ids) {
if (ids == null || ids.size() == 0)
return "";
else if (ids.size() == 1)
return "1 Vulnerability has ";
else
return ids.size() + " Vulnerabilities have ";
}
}