Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
KaterynaHonchar committed Jun 30, 2017
2 parents 820cfd0 + bdd2cf4 commit 07965c0
Show file tree
Hide file tree
Showing 9 changed files with 418 additions and 14 deletions.
@@ -0,0 +1,173 @@
package com.evolveum.midpoint.gui.impl.util;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.TypeFilter;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.security.MidPointApplication;
import com.evolveum.midpoint.xml.ns._public.common.common_3.NodeType;

import org.apache.commons.io.IOUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.List;

public class ReportPeerQueryInterceptor extends HttpServlet {

private static final long serialVersionUID = 7612750211021974750L;
private static String MIDPOINT_HOME = System.getProperty("midpoint.home");
private static String EXPORT_DIR = MIDPOINT_HOME + "export/";
private static String HEADER_USERAGENT = "mp-cluser-peer-client";
private static String DEFAULTMIMETYPE = "application/octet-stream";
private static String FILENAMEPARAMETER = "fname";
private static String URLENCODING = "UTF-8";

private static final String INTERCEPTOR_CLASS = ReportPeerQueryInterceptor.class.getName() + ".";
private static final String OPERATION_LIST_NODES = INTERCEPTOR_CLASS + "listNodes";

private static final Trace LOGGER = TraceManager.getTrace(ReportPeerQueryInterceptor.class);

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userAgent = request.getHeader("User-Agent");
String remoteName = request.getRemoteHost();
if (!HEADER_USERAGENT.equals(userAgent)) {
LOGGER.debug("Invalid user-agent: {}", userAgent);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else if (!isKnownNode(remoteName, "File retrieval")) {
LOGGER.debug("Unknown node, host: {} ", remoteName);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
String fileName = request.getParameter(FILENAMEPARAMETER);
fileName = URLDecoder.decode(fileName, URLENCODING);
StringBuilder buildfilePath = new StringBuilder(EXPORT_DIR).append(fileName);
String filePath = buildfilePath.toString();

File loadedFile = new File(filePath);
if (!loadedFile.exists()) {
StringBuilder errorBuilder = new StringBuilder("Download operation not successful. The file: ")
.append(fileName).append(" was not found on the filesystem");
LOGGER.warn(errorBuilder.toString());
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
} else if (loadedFile.isDirectory()) {
StringBuilder errorBuilder = new StringBuilder("Download operation not successful. Attempt to download a directory with the name: ")
.append(fileName).append(" this operation is prohibited.");
LOGGER.warn(errorBuilder.toString());
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
FileInputStream fileInputStream = new FileInputStream(filePath);

ServletContext context = getServletContext();
String mimeType = context.getMimeType(filePath);

if (mimeType == null) {
// MIME mapping not found
mimeType = DEFAULTMIMETYPE;
}

response.setContentType(mimeType);
response.setContentLength((int) loadedFile.length());

StringBuilder headerValue = new StringBuilder("attachment; filename=\"%s\"").append(fileName);
response.setHeader("Content-Disposition", headerValue.toString());

OutputStream outputStream = response.getOutputStream();

byte[] buffer = new byte[1024];
int len;
while ((len = fileInputStream.read(buffer)) > -1) {
outputStream.write(buffer, 0, len);
}
IOUtils.closeQuietly(fileInputStream);
IOUtils.closeQuietly(outputStream);
LOGGER.trace("The file {} has been dispatched to the client.", fileName);
}
}
}

@Override
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException {

String userAgent = request.getHeader("User-Agent");
String remoteName = request.getRemoteHost();
if (!HEADER_USERAGENT.equals(userAgent)) {
LOGGER.debug("Invalid user-agent: {}", userAgent);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else if (!isKnownNode(remoteName, "File deletion")) {
LOGGER.debug("Unknown node, host: {} ", remoteName);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
String fileName = request.getParameter(FILENAMEPARAMETER);
fileName = URLDecoder.decode(fileName, URLENCODING);
StringBuilder buildfilePath = new StringBuilder(EXPORT_DIR).append(fileName);
String filePath = buildfilePath.toString();
File reportFile = new File(filePath);
if (!reportFile.exists()) {
StringBuilder errorBuilder = new StringBuilder("Delete operation not successful. The file: ").append(fileName)
.append(" was not found on the filesystem.");
LOGGER.warn(errorBuilder.toString());
response.sendError(HttpServletResponse.SC_NOT_FOUND);

} else if (reportFile.isDirectory()) {
StringBuilder errorBuilder = new StringBuilder("Delete operation not successful. Attempt to Delete a directory with the name: ")
.append(fileName).append(" This operation is prohibited.");
LOGGER.warn(errorBuilder.toString());
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
reportFile.delete();
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
LOGGER.trace("Deletion of the file {} has finished.", fileName);
}
}

protected RepositoryService getRepositoryService() {
MidPointApplication application = (MidPointApplication) MidPointApplication.get();
return application.getRepositoryService();
}

protected TaskManager getTaskManager() {
MidPointApplication application = (MidPointApplication) MidPointApplication.get();
return application.getTaskManager();
}

protected Boolean isKnownNode(String remoteName, String operation) {

LOGGER.info("Checking if {} is a known node", remoteName);
OperationResult result = new OperationResult(OPERATION_LIST_NODES);
try {
ObjectQuery query = new ObjectQuery();
TypeFilter filter = TypeFilter.createType(NodeType.COMPLEX_TYPE, null);
query.addFilter(filter);
List<PrismObject<NodeType>> knownNodes = getRepositoryService().searchObjects(NodeType.class, null, null, result);
for (PrismObject<NodeType> node : knownNodes) {
NodeType actualNode = node.asObjectable();
if (remoteName.equals(actualNode.getHostname())) {
LOGGER.trace("The node {} was recognized as a known node. Attempting to execute the requested operation: {} ", actualNode.getHostname(), operation);
return true;
}
}

} catch (Exception e) {
LOGGER.error("Unhandled exception when listing nodes");
LoggingUtils.logUnexpectedException(LOGGER, "Unhandled exception when listing nodes", e);
}
return false;
}

}
11 changes: 11 additions & 0 deletions gui/admin-gui/src/main/webapp/WEB-INF/web.xml
Expand Up @@ -148,6 +148,17 @@
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet>
<servlet-name>ReportPeerQueryInterceptor</servlet-name>
<servlet-class>com.evolveum.midpoint.gui.impl.util.ReportPeerQueryInterceptor</servlet-class>
</servlet>


<servlet-mapping>
<servlet-name>ReportPeerQueryInterceptor</servlet-name>
<url-pattern>/report</url-pattern>
</servlet-mapping>
<servlet-mapping>
<!-- Deprecated -->
<servlet-name>CXFServlet</servlet-name>
Expand Down
Expand Up @@ -22,6 +22,7 @@
import com.evolveum.midpoint.prism.xnode.PrimitiveXNode;
import com.evolveum.midpoint.prism.xnode.XNode;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ApprovalSchemaType;
Expand All @@ -41,6 +42,8 @@
import java.util.Date;

/**
* TODO unify with PrettyPrinter somehow
*
* @author mederly
*/
public class ValueDisplayUtil {
Expand Down Expand Up @@ -137,6 +140,8 @@ public static String toStringValue(PrismPropertyValue propertyValue) {
return String.valueOf(value);
} else if (value instanceof byte[]) {
return "(binary data)";
} else if (value instanceof RawType) {
return PrettyPrinter.prettyPrint(value);
} else {
return "(a value of type " + value.getClass().getSimpleName() + ")"; // todo i18n
}
Expand Down
Expand Up @@ -844,7 +844,7 @@ public static <F extends ObjectType> boolean evaluateIterationCondition(LensCont
variables.addVariableDefinition(ExpressionConstants.VAR_ITERATION_TOKEN, iterationToken);

ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(null , variables, desc, task, result);
PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> outputTriple = ModelExpressionThreadLocalHolder.evaluateExpressionInContext(expression, expressionContext, task, result);
PrismValueDeltaSetTriple<PrismPropertyValue<Boolean>> outputTriple = ModelExpressionThreadLocalHolder.evaluateExpressionInContext(expression, expressionContext, context, null, task, result);
Collection<PrismPropertyValue<Boolean>> outputValues = outputTriple.getNonNegativeValues();
if (outputValues.isEmpty()) {
return false;
Expand Down
Expand Up @@ -84,7 +84,10 @@
<cap:enableValue>false</cap:enableValue>
<cap:disableValue>true</cap:disableValue>
</cap:status>
</cap:activation>
</cap:activation>
<!-- <cap:addRemoveAttributeValues>
<cap:enabled>false</cap:enabled>
</cap:addRemoveAttributeValues> -->
</configured>
</capabilities>
</additionalConnector>
Expand Down Expand Up @@ -153,6 +156,21 @@
</objectType>
</schemaHandling>

<capabilities>
<configured>
<cap:activation>
<cap:status>
<cap:attribute>ri:disabled</cap:attribute>
<cap:enableValue>false</cap:enableValue>
<cap:disableValue>true</cap:disableValue>
</cap:status>
</cap:activation>
<!-- <cap:addRemoveAttributeValues>
<cap:enabled>false</cap:enabled>
</cap:addRemoveAttributeValues> -->
</configured>
</capabilities>

<consistency>
<avoidDuplicateValues>true</avoidDuplicateValues>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
Expand Down
Expand Up @@ -130,6 +130,18 @@
</objectType>
</schemaHandling>

<capabilities>
<configured>
<cap:activation>
<cap:status>
<cap:attribute>ri:disabled</cap:attribute>
<cap:enableValue>false</cap:enableValue>
<cap:disableValue>true</cap:disableValue>
</cap:status>
</cap:activation>
</configured>
</capabilities>

<consistency>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
</consistency>
Expand Down
23 changes: 19 additions & 4 deletions model/report-impl/pom.xml
Expand Up @@ -143,7 +143,7 @@
<version>20060411</version>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
Expand All @@ -165,8 +165,23 @@
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>

<!-- Test -->

<!-->Dependency definnition added, client to fetch reports <-->

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.6</version>
</dependency>


<!-- Test -->
<dependency>
<groupId>com.evolveum.midpoint.repo</groupId>
<artifactId>repo-cache</artifactId>
Expand Down Expand Up @@ -281,5 +296,5 @@
<version>1.2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencies>
</project>
Expand Up @@ -62,7 +62,6 @@
import javax.xml.datatype.XMLGregorianCalendar;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
Expand Down Expand Up @@ -331,11 +330,27 @@ public void deleteReportOutput(ReportOutputType reportOutput, OperationResult pa
parentResult.addSubresult(task.getResult());
OperationResult result = parentResult.createSubresult(DELETE_REPORT_OUTPUT);


String filePath = reportOutput.getFilePath();
result.addParam("oid", oid);
try {
File reportFile = new File(reportOutput.getFilePath());
reportFile.delete();

File reportFile = new File(filePath);

if(reportFile.exists()){
reportFile.delete();
}else {
ObjectReferenceType nodeRef =reportOutput.getNodeRef();
String nodeOid= nodeRef.getOid();
NodeType node = modelService.getObject(NodeType.class, nodeOid,null,null,parentResult).asObjectable();
SystemConfigurationType systemConfig = modelService.getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(),null,task,result).asObjectable();
String icUrlPattern = systemConfig.getInfrastructure().getIntraClusterHttpUrlPattern();
String hostName = node.getHostname();;
ReportNodeUtils nodeUtils = new ReportNodeUtils();
String [] splitted = filePath.split("/");
String filename= splitted[splitted.length-1];
nodeUtils.executeOperation(hostName,filename,icUrlPattern,"DELETE");
}

ObjectDelta<ReportOutputType> delta = ObjectDelta.createDeleteDelta(ReportOutputType.class, oid, prismContext);
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(delta);

Expand Down Expand Up @@ -369,12 +384,27 @@ public InputStream getReportOutputData(String reportOutputOid, OperationResult p
return null;
}
File file = new File(filePath);
reportData = FileUtils.openInputStream(file);

if(file.exists()){

reportData = FileUtils.openInputStream(file);

}else{
ObjectReferenceType nodeRef =reportOutput.getNodeRef();
String nodeOid= nodeRef.getOid();
NodeType node = modelService.getObject(NodeType.class, nodeOid,null,null,parentResult).asObjectable();
String hostName = node.getHostname();

SystemConfigurationType systemConfig = modelService.getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(),null,task,result).asObjectable();
String icUrlPattern = systemConfig.getInfrastructure().getIntraClusterHttpUrlPattern();
ReportNodeUtils nodeUtils = new ReportNodeUtils();
String [] splitted = filePath.split("/");
String filename= splitted[splitted.length-1];
reportData = nodeUtils.executeOperation(hostName,filename,icUrlPattern,"GET");
}
result.recordSuccessIfUnknown();
} catch (IOException ex) {
LOGGER.error("Report doesn't exist anymore.");
result.recordPartialError("Report doesn't exist anymore.");
LOGGER.error("Error while fetching file. File might not exist on the corresponding file system");
result.recordPartialError("Error while fetching file. File might not exist on the corresponding file system.");
throw ex;
} catch (ObjectNotFoundException | SchemaException | SecurityViolationException | CommunicationException
| ConfigurationException | ExpressionEvaluationException e) {
Expand Down

0 comments on commit 07965c0

Please sign in to comment.