package jetbrains.buildserver.sonarplugin.sqrunner; import jetbrains.buildServer.controllers.BaseAjaxActionController; import jetbrains.buildServer.controllers.PublicKeyUtil; import jetbrains.buildServer.serverSide.ConfigAction; import jetbrains.buildServer.serverSide.ConfigActionFactory; import jetbrains.buildServer.serverSide.ProjectManager; import jetbrains.buildServer.serverSide.SProject; import jetbrains.buildServer.serverSide.auth.AuthUtil; import jetbrains.buildServer.serverSide.auth.SecurityContext; import jetbrains.buildServer.serverSide.crypt.RSACipher; import jetbrains.buildServer.util.StringUtil; import jetbrains.buildServer.web.openapi.ControllerAction; import jetbrains.buildServer.web.openapi.WebControllerManager; import jetbrains.buildserver.sonarplugin.sqrunner.manager.SQSInfo; import jetbrains.buildserver.sonarplugin.sqrunner.manager.SQSInfoFactory; import jetbrains.buildserver.sonarplugin.sqrunner.manager.SQSManager; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by Andrery Titov on 4/10/14. * * Ajax controller for SonarQube Server management */ public class ManageSQSActionController extends BaseAjaxActionController implements ControllerAction { private static final String SERVERINFO_ID = "serverinfo.id"; private static final String SERVERINFO_NAME = "serverinfo.name"; private static final String SONAR_URL = "sonar.host.url"; private static final String SONAR_LOGIN = "sonar.login"; private static final String SONAR_PASSWORD = "sonar.password"; private static final String SONAR_PASSWORD_PRESERVE = "sonar.password_preserve"; private static final String SONAR_JDBC_URL = "sonar.jdbc.url"; private static final String SONAR_JDBC_USERNAME = "sonar.jdbc.username"; private static final String SONAR_JDBC_PASSWORD = "sonar.jdbc.password"; private static final String SONAR_JDBC_PASSWORD_PRESERVE = "sonar.jdbc.password_preserve"; private static final String ADD_SQS_ACTION = "addSqs"; private static final String REMOVE_SQS_ACTION = "removeSqs"; private static final String EDIT_SQS_ACTION = "editSqs"; private static final String SQS_ACTION = "action"; @NotNull private final SQSManager mySqsManager; @NotNull private final ProjectManager myProjectManager; @NotNull private final SecurityContext securityContext; @NotNull private final SQSInfoFactory mySQSInfoFactory; @NotNull private final ConfigActionFactory myConfigActionFactory; public ManageSQSActionController(@NotNull final WebControllerManager controllerManager, @NotNull final SQSManager sqsManager, @NotNull final ProjectManager projectManager, @NotNull final SecurityContext securityContext, @NotNull final SQSInfoFactory sqsInfoFactory, @NotNull final ConfigActionFactory configActionFactory) { super(controllerManager); mySQSInfoFactory = sqsInfoFactory; myConfigActionFactory = configActionFactory; controllerManager.registerController("/admin/manageSonarServers.html", this); registerAction(this); mySqsManager = sqsManager; myProjectManager = projectManager; this.securityContext = securityContext; } public boolean canProcess(@NotNull final HttpServletRequest request) { final String action = getAction(request); return ADD_SQS_ACTION.equals(action) || EDIT_SQS_ACTION.equals(action) || REMOVE_SQS_ACTION.equals(action); } private static String getAction(@NotNull final HttpServletRequest request) { return request.getParameter(SQS_ACTION); } public void process(@NotNull final HttpServletRequest request, @NotNull final HttpServletResponse response, @Nullable final Element ajaxResponse) { final SProject project = getProject(request); if (ajaxResponse == null || project == null) { return; } // Security test (user without management permission could access this controller) if (!AuthUtil.hasPermissionToManageProject(securityContext.getAuthorityHolder(), project.getProjectId())){ ajaxResponse.setAttribute("error", "User has not the management permission"); return; } final String action = getAction(request); try { ConfigAction configAction = null; if (ADD_SQS_ACTION.equals(action)) { final SQSInfo sqsInfo = addServerInfo(request, project, ajaxResponse); if (sqsInfo != null) { configAction = myConfigActionFactory.createAction(project, "SonarQube Server '" + sqsInfo.getName() + "' was added"); } } else if (REMOVE_SQS_ACTION.equals(action)) { final SQSInfo sqsInfo = removeServerInfo(request, project, ajaxResponse); if (sqsInfo != null) { configAction = myConfigActionFactory.createAction(project, "SonarQube Server '" + sqsInfo.getName() + "' was removed"); } } else if (EDIT_SQS_ACTION.equals(action)) { final SQSInfo sqsInfo = editServerInfo(request, project, ajaxResponse); if (sqsInfo != null) { configAction = myConfigActionFactory.createAction(project, "parameters of SonarQube Server '" + sqsInfo.getName() + "' were changed"); } } if (configAction != null) { project.persist(configAction); } } catch (IOException e) { ajaxResponse.setAttribute("error", "Exception occurred: " + e.getMessage()); } } private SQSInfo editServerInfo(@NotNull final HttpServletRequest request, @NotNull final SProject project, @NotNull final Element ajaxResponse) { if (!validate(request, ajaxResponse)) { return null; } final String serverInfoId = getServerInfoId(request); if (serverInfoId == null) { ajaxResponse.setAttribute("error", "ID is not set"); return null; } final SQSInfo old = mySqsManager.getServer(project, serverInfoId); if (old == null) { return null; } final String pass = getPassword(request, old); final String jdbcPass = getJDBCPassword(request, old); final SQSInfo info = createServerInfo(request, serverInfoId, pass, jdbcPass); final SQSManager.SQSActionResult result = mySqsManager.editServer(project, info); if (!result.isError()) { ajaxResponse.setAttribute("status", "OK"); } else { ajaxResponse.setAttribute("error", result.getReason()); } return result.getAfterAction(); } @Nullable private String getJDBCPassword(@NotNull final HttpServletRequest request, @NotNull final SQSInfo old) { return Boolean.parseBoolean(request.getParameter(SONAR_JDBC_PASSWORD_PRESERVE)) ? old.getJDBCPassword() : decryptIfNeeded(request.getParameter(SONAR_JDBC_PASSWORD)); } @Nullable private String getPassword(@NotNull HttpServletRequest request, @NotNull final SQSInfo old) { return Boolean.parseBoolean(request.getParameter(SONAR_PASSWORD_PRESERVE)) ? old.getPassword() : decryptIfNeeded(request.getParameter(SONAR_PASSWORD)); } @NotNull private SQSInfo createServerInfo(@NotNull HttpServletRequest request, String serverInfoId, String pass, String jdbcPass) { return mySQSInfoFactory.create(serverInfoId, StringUtil.nullIfEmpty(request.getParameter(SERVERINFO_NAME)), StringUtil.nullIfEmpty(request.getParameter(SONAR_URL)), StringUtil.nullIfEmpty(request.getParameter(SONAR_LOGIN)), StringUtil.nullIfEmpty(pass), StringUtil.nullIfEmpty(request.getParameter(SONAR_JDBC_URL)), StringUtil.nullIfEmpty(request.getParameter(SONAR_JDBC_USERNAME)), StringUtil.nullIfEmpty(jdbcPass)); } private String decryptIfNeeded(@Nullable final String value) { return value != null ? RSACipher.decryptWebRequestData(value) : null; } private SQSInfo removeServerInfo(@NotNull final HttpServletRequest request, @NotNull final SProject project, @NotNull final Element ajaxResponse) throws IOException { final String serverinfoId = getServerInfoId(request); if (serverinfoId == null) { ajaxResponse.setAttribute("error", "ID is not set"); } else { final SQSManager.SQSActionResult result = mySqsManager.removeServer(project, serverinfoId); if (!result.isError()) { ajaxResponse.setAttribute("status", result.getReason()); return result.getBeforeAction(); } else { ajaxResponse.setAttribute("error", result.getReason()); } } return null; } private SQSInfo addServerInfo(@NotNull final HttpServletRequest request, @NotNull final SProject project, @NotNull final Element ajaxResponse) throws IOException { if (validate(request, ajaxResponse)) { final SQSInfo serverInfo = createServerInfo(request, null, decryptIfNeeded(request.getParameter(SONAR_PASSWORD)), decryptIfNeeded(request.getParameter(SONAR_JDBC_PASSWORD))); final SQSManager.SQSActionResult result = mySqsManager.addServer(project, serverInfo); if (!result.isError()) { ajaxResponse.setAttribute("status", "OK"); } else { ajaxResponse.setAttribute("error", result.getReason()); } return serverInfo; } return null; } private boolean validate(HttpServletRequest request, Element ajaxResponse) { if (request.getParameter("publicKey") != null && PublicKeyUtil.isPublicKeyExpired(request)) { PublicKeyUtil.writePublicKeyExpiredError(ajaxResponse); return false; } if (request.getParameter(SERVERINFO_NAME) == null) { ajaxResponse.setAttribute("error", "Server name should be set"); return false; } if (request.getParameter(SONAR_URL) == null) { ajaxResponse.setAttribute("error", "Server url should be explicitly set"); return false; } return true; } @Nullable private SProject getProject(@NotNull final HttpServletRequest request) { return myProjectManager.findProjectByExternalId(request.getParameter("projectId")); } private static String getServerInfoId(@NotNull final HttpServletRequest request) { return request.getParameter(SERVERINFO_ID); } }