////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009-2013 Denim Group, Ltd.
//
// The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is ThreadFix.
//
// The Initial Developer of the Original Code is Denim Group, Ltd.
// Portions created by Denim Group, Ltd. are Copyright (C)
// Denim Group, Ltd. All Rights Reserved.
//
// Contributor(s): Denim Group, Ltd.
//
////////////////////////////////////////////////////////////////////////
package com.denimgroup.threadfix.webapp.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import com.denimgroup.threadfix.data.entities.Permission;
import com.denimgroup.threadfix.data.entities.RemoteProviderApplication;
import com.denimgroup.threadfix.data.entities.RemoteProviderType;
import com.denimgroup.threadfix.service.OrganizationService;
import com.denimgroup.threadfix.service.PermissionService;
import com.denimgroup.threadfix.service.RemoteProviderApplicationService;
import com.denimgroup.threadfix.service.RemoteProviderTypeService;
import com.denimgroup.threadfix.service.RemoteProviderTypeService.ResponseCode;
import com.denimgroup.threadfix.service.SanitizedLogger;
@Controller
@RequestMapping("configuration/remoteproviders")
@SessionAttributes(value= {"remoteProviderType", "remoteProviderApplication"})
public class RemoteProvidersController {
public RemoteProvidersController(){}
private final SanitizedLogger log = new SanitizedLogger(RemoteProvidersController.class);
private RemoteProviderTypeService remoteProviderTypeService;
private PermissionService permissionService;
private RemoteProviderApplicationService remoteProviderApplicationService;
private OrganizationService organizationService;
@Autowired
public RemoteProvidersController(RemoteProviderTypeService remoteProviderTypeService,
RemoteProviderApplicationService remoteProviderApplicationService,
PermissionService permissionService, OrganizationService organizationService) {
this.remoteProviderTypeService = remoteProviderTypeService;
this.remoteProviderApplicationService = remoteProviderApplicationService;
this.organizationService = organizationService;
this.permissionService = permissionService;
}
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setAllowedFields(new String[] { "apiKey", "username",
"password", "application.id", "application.organization.id", "isEuropean" });
}
@RequestMapping(method = RequestMethod.GET)
public String index(Model model, HttpServletRequest request) {
log.info("Processing request for Remote Provider index.");
List<RemoteProviderType> typeList = remoteProviderTypeService.loadAll();
for (RemoteProviderType type : typeList) {
if (type != null && type.getApiKey() != null) {
type.setApiKey(mask(type.getApiKey()));
}
}
model.addAttribute("successMessage", ControllerUtils.getSuccessMessage(request));
model.addAttribute("errorMessage", ControllerUtils.getErrorMessage(request));
permissionService.filterApps(typeList);
model.addAttribute("remoteProviders", typeList);
model.addAttribute("remoteProviderType", new RemoteProviderType());
model.addAttribute("remoteProviderApplication", new RemoteProviderApplication());
model.addAttribute("organizationList", organizationService.loadAllActiveFilter());
permissionService.addPermissions(model, null, null, Permission.CAN_MANAGE_REMOTE_PROVIDERS);
return "config/remoteproviders/index";
}
private String mask(String input) {
if (input != null) {
if (input.length() > 5) {
String replaced = input.replace(input.substring(0,input.length() - 4),
RemoteProviderTypeService.API_KEY_PREFIX);
return replaced;
} else {
// should never get here, but let's not return the info anyway
return RemoteProviderTypeService.API_KEY_PREFIX;
}
} else {
return null;
}
}
@RequestMapping(value="/{typeId}/update", method = RequestMethod.GET)
public String updateApps(@PathVariable("typeId") int typeId, HttpServletRequest request) {
log.info("Processing request for RemoteProviderType update.");
RemoteProviderType remoteProviderType = remoteProviderTypeService.load(typeId);
remoteProviderApplicationService.updateApplications(remoteProviderType);
remoteProviderTypeService.store(remoteProviderType);
ControllerUtils.addSuccessMessage(request, "ThreadFix updated applications from " +
remoteProviderType + ".");
return "redirect:/configuration/remoteproviders/";
}
@RequestMapping(value="/{typeId}/importAll", method = RequestMethod.GET)
public String importAllScans(@PathVariable("typeId") int typeId, HttpServletRequest request) {
log.info("Processing request for RemoteProviderType bulk import.");
RemoteProviderType remoteProviderType = remoteProviderTypeService.load(typeId);
remoteProviderApplicationService.addBulkImportToQueue(remoteProviderType);
ControllerUtils.addSuccessMessage(request, "ThreadFix is importing scans from " + remoteProviderType +
" in the background. It may take a few minutes to finish the process.");
return "redirect:/configuration/remoteproviders/";
}
@RequestMapping(value="/{typeId}/apps/{appId}/import", method = RequestMethod.GET)
public String importScan(@PathVariable("typeId") int typeId,
HttpServletRequest request, @PathVariable("appId") int appId) {
log.info("Processing request for scan import.");
RemoteProviderApplication remoteProviderApplication = remoteProviderApplicationService.load(appId);
if (remoteProviderApplication == null || remoteProviderApplication.getApplication() == null) {
request.getSession().setAttribute("errorMessage",
"The scan request failed because it could not find the requested application.");
return "redirect:/configuration/remoteproviders/";
}
if (remoteProviderApplication.getApplication().getId() == null ||
remoteProviderApplication.getApplication().getOrganization() == null ||
remoteProviderApplication.getApplication().getOrganization().getId() == null ||
!permissionService.isAuthorized(Permission.CAN_UPLOAD_SCANS,
remoteProviderApplication.getApplication().getOrganization().getId(),
remoteProviderApplication.getApplication().getId())) {
return "403";
}
remoteProviderTypeService.decryptCredentials(
remoteProviderApplication.getRemoteProviderType());
if (remoteProviderApplicationService.importScansForApplication(remoteProviderApplication)) {
return "redirect:/organizations/" +
remoteProviderApplication.getApplication().getOrganization().getId() +
"/applications/" +
remoteProviderApplication.getApplication().getId();
} else {
request.getSession().setAttribute("errorMessage", "No new scans were found.");
return "redirect:/configuration/remoteproviders/";
}
}
@PreAuthorize("hasRole('ROLE_CAN_MANAGE_REMOTE_PROVIDERS')")
@RequestMapping(value="/{typeId}/apps/{appId}/edit", method = RequestMethod.POST)
public String configureAppSubmit(@PathVariable("typeId") int typeId, @PathVariable("appId") int appId,
@Valid @ModelAttribute RemoteProviderApplication remoteProviderApplication,
BindingResult result, SessionStatus status,
Model model, HttpServletRequest request) {
if (result.hasErrors() || remoteProviderApplication.getApplication() == null) {
return "config/remoteproviders/edit";
} else {
// permissionService.isAuthorized(Permission.CAN_MANAGE_REMOTE_PROVIDERS, null, null);
RemoteProviderApplication dbRemoteProviderApplication =
remoteProviderApplicationService.load(appId);
dbRemoteProviderApplication.setApplication(remoteProviderApplication.getApplication());
remoteProviderApplicationService.processApp(result, dbRemoteProviderApplication);
if (result.hasErrors()) {
String error = "Invalid submission.";
model.addAttribute("errorMessage", error);
model.addAttribute("remoteProviderApplication",remoteProviderApplication);
model.addAttribute("contentPage", "config/remoteproviders/editMapping.jsp");
model.addAttribute("organizationList", organizationService.loadAllActiveFilter());
return "ajaxFailureHarness";
}
ControllerUtils.addSuccessMessage(request, "Application successfully updated.");
model.addAttribute("contentPage", "/configuration/remoteproviders");
return "ajaxRedirectHarness";
}
}
@PreAuthorize("hasRole('ROLE_CAN_MANAGE_REMOTE_PROVIDERS')")
@RequestMapping(value="/{typeId}/configure", method = RequestMethod.POST)
public String configureFinish(@PathVariable("typeId") int typeId,
HttpServletRequest request, Model model) {
ResponseCode test = remoteProviderTypeService.checkConfiguration(
request.getParameter("username"),
request.getParameter("password"),
request.getParameter("apiKey"), typeId);
if (test.equals(ResponseCode.BAD_ID)) {
return "403";
} else if (test.equals(ResponseCode.NO_APPS)) {
String error = "We were unable to retrieve a list of applications using these credentials." +
" Please ensure that the credentials are valid and that there are applications " +
"available in the account.";
model.addAttribute("errorMessage", error);
model.addAttribute("remoteProviderType", remoteProviderTypeService.load(typeId));
model.addAttribute("contentPage", "config/remoteproviders/configure.jsp");
return "ajaxFailureHarness";
} else if (test.equals(ResponseCode.SUCCESS)) {
ControllerUtils.addSuccessMessage(request, "Applications successfully updated.");
model.addAttribute("contentPage", "/configuration/remoteproviders");
return "ajaxRedirectHarness";
} else {
ControllerUtils.addErrorMessage(request, "An unidentified error occurred.");
model.addAttribute("contentPage", "/configuration/remoteproviders");
return "ajaxRedirectHarness";
}
}
@PreAuthorize("hasRole('ROLE_CAN_MANAGE_REMOTE_PROVIDERS')")
@RequestMapping(value="/{typeId}/clearConfiguration", method = RequestMethod.POST)
public String clearConfiguration(@PathVariable("typeId") int typeId,
HttpServletRequest request) {
RemoteProviderType type = remoteProviderTypeService.load(typeId);
if (type != null) {
remoteProviderTypeService.clearConfiguration(typeId);
ControllerUtils.addSuccessMessage(request, type.getName() + " configuration was cleared successfully.");
}
return "redirect:/configuration/remoteproviders";
}
}