Skip to content

Commit

Permalink
REST: changed debugPrintObject to t:object for root XML object in RES…
Browse files Browse the repository at this point in the history
…T responses.

Bulk actions: separated "filterContent" from "select" expression. Changed xmlData to dataOutput in the output structure.
  • Loading branch information
mederly committed May 15, 2017
1 parent 24b78fd commit 2aa3a27
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 59 deletions.
Expand Up @@ -399,7 +399,7 @@
<xsd:complexType name="SingleScriptOutputType">
<xsd:sequence>
<xsd:choice>
<xsd:element name="xmlData" type="s:PipelineDataType" />
<xsd:element name="dataOutput" type="s:PipelineDataType" />
<xsd:element name="mslData" type="xsd:string" />
</xsd:choice>
<xsd:element name="textOutput" type="xsd:string" minOccurs="0" />
Expand Down
Expand Up @@ -300,14 +300,35 @@
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="tns:ScriptingExpressionType">
<xsd:choice>
<xsd:sequence>
<xsd:element name="path" type="t:ItemPathType">
<xsd:annotation>
<xsd:documentation>
Path to the data item that has to be selected.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="select" type="tns:SelectExpressionType" substitutionGroup="tns:scriptingExpression" >
<xsd:annotation>
<xsd:appinfo>
<a:heterogeneousListItem/>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>

<xsd:complexType name="FilterContentExpressionType">
<xsd:annotation>
<xsd:documentation>
Keeps/removes selected items from the input value.
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="tns:ScriptingExpressionType">
<xsd:choice>
<xsd:element name="keep" type="t:ItemPathType" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Expand All @@ -326,7 +347,7 @@
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="select" type="tns:SelectExpressionType" substitutionGroup="tns:scriptingExpression" >
<xsd:element name="filterContent" type="tns:FilterContentExpressionType" substitutionGroup="tns:scriptingExpression" >
<xsd:annotation>
<xsd:appinfo>
<a:heterogeneousListItem/>
Expand Down
Expand Up @@ -23,14 +23,11 @@
import com.evolveum.midpoint.model.impl.rest.PATCH;
import com.evolveum.midpoint.model.impl.security.SecurityHelper;
import com.evolveum.midpoint.model.impl.util.RestServiceUtil;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.crypto.EncryptionException;
import com.evolveum.midpoint.prism.crypto.Protector;
import com.evolveum.midpoint.prism.delta.ItemDelta;
Expand Down Expand Up @@ -1085,7 +1082,7 @@ public <T extends ObjectType> Response executeScript(ScriptingExpressionType scr
operationOutput.setOutputs(outputs);
SingleScriptOutputType output = new SingleScriptOutputType();
output.setTextOutput(executionResult.getConsoleOutput());
output.setXmlData(ModelWebService.prepareXmlData(executionResult.getDataOutput()));
output.setDataOutput(ModelWebService.prepareXmlData(executionResult.getDataOutput()));
outputs.getOutput().add(output);

builder = Response.ok();
Expand Down
Expand Up @@ -262,7 +262,7 @@ private ExecuteScriptsResponseType doExecuteScripts(List<JAXBElement<?>> scripts

output.setTextOutput(executionResult.getConsoleOutput());
if (options == null || options.getOutputFormat() == null || options.getOutputFormat() == OutputFormatType.XML) {
output.setXmlData(prepareXmlData(executionResult.getDataOutput()));
output.setDataOutput(prepareXmlData(executionResult.getDataOutput()));
} else {
// temporarily we send serialized XML in the case of MSL output
PipelineDataType jaxbOutput = prepareXmlData(executionResult.getDataOutput());
Expand Down
Expand Up @@ -87,7 +87,7 @@ public void writeTo(T object, Class<?> type, Type genericType,
WebApplicationException {

// TODO implement in the standard serializer; also change root name
QName fakeQName = new QName(PrismConstants.NS_PREFIX + "debug", "debugPrintObject");
QName fakeQName = new QName(PrismConstants.NS_TYPES, "object");
String xml;

PrismSerializer<String> serializer = getSerializer();
Expand Down
Expand Up @@ -17,6 +17,7 @@
package com.evolveum.midpoint.model.impl.scripting;

import com.evolveum.midpoint.model.api.ScriptExecutionException;
import com.evolveum.midpoint.model.impl.scripting.expressions.FilterContentEvaluator;
import com.evolveum.midpoint.model.impl.scripting.expressions.SearchEvaluator;
import com.evolveum.midpoint.model.impl.scripting.expressions.SelectEvaluator;
import com.evolveum.midpoint.model.impl.scripting.helpers.JaxbHelper;
Expand Down Expand Up @@ -57,6 +58,7 @@ public class ScriptingExpressionEvaluator {
@Autowired private TaskManager taskManager;
@Autowired private SearchEvaluator searchEvaluator;
@Autowired private SelectEvaluator selectEvaluator;
@Autowired private FilterContentEvaluator filterContentEvaluator;
@Autowired private JaxbHelper jaxbHelper;
@Autowired private PrismContext prismContext;

Expand Down Expand Up @@ -180,6 +182,8 @@ public PipelineData evaluateExpression(ScriptingExpressionType value, PipelineDa
output = executeSequence((ExpressionSequenceType) value, input, context, globalResult);
} else if (value instanceof SelectExpressionType) {
output = selectEvaluator.evaluate((SelectExpressionType) value, input, context, globalResult);
} else if (value instanceof FilterContentExpressionType) {
output = filterContentEvaluator.evaluate((FilterContentExpressionType) value, input, context, globalResult);
} else if (value instanceof SearchExpressionType) {
output = searchEvaluator.evaluate((SearchExpressionType) value, input, context, globalResult);
} else if (value instanceof ActionExpressionType) {
Expand Down
Expand Up @@ -27,13 +27,15 @@
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand Down Expand Up @@ -74,13 +76,8 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input,
try {
LOGGER.trace("Generating password for {}", userObject);
// TODO unify with ModelRestService.generateValue
CredentialsPolicyType policy = modelInteraction.getCredentialsPolicy(userObject, context.getTask(), result);
if (policy == null || policy.getPassword() == null || policy.getPassword().getPasswordPolicyRef() == null) {
throw new ObjectNotFoundException("No applicable password policy found");
}
ValuePolicyType valuePolicy = modelService.getObject(ValuePolicyType.class,
policy.getPassword().getPasswordPolicyRef().getOid(), null, context.getTask(), result).asObjectable();
String newClearValue = policyProcessor.generate(valuePolicy.getStringPolicy(), 10, userObject,
ValuePolicyType valuePolicy = getPasswordPolicy(context, result, userObject);
String newClearValue = policyProcessor.generate(SchemaConstants.PATH_PASSWORD_VALUE, valuePolicy.getStringPolicy(), 10, userObject,
"generating value for password", context.getTask(), result);
ProtectedStringType newValue = new ProtectedStringType();
newValue.setClearValue(newClearValue);
Expand All @@ -103,4 +100,27 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input,
}
return input;
}

@NotNull
private ValuePolicyType getPasswordPolicy(ExecutionContext context, OperationResult result, PrismObject<UserType> userObject)
throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
CredentialsPolicyType policy = modelInteraction.getCredentialsPolicy(userObject, context.getTask(), result);
if (policy != null && policy.getPassword() != null && policy.getPassword().getPasswordPolicyRef() != null) {
return resolvePolicyRef(policy.getPassword().getPasswordPolicyRef().getOid(), context, result);
}
SystemConfigurationType systemConfiguration = modelInteraction.getSystemConfiguration(result);
if (systemConfiguration.getGlobalPasswordPolicyRef() != null
&& systemConfiguration.getGlobalPasswordPolicyRef().getOid() != null) {
return resolvePolicyRef(systemConfiguration.getGlobalPasswordPolicyRef().getOid(), context, result);
}
throw new ObjectNotFoundException("No applicable password policy found");
}

@NotNull
private ValuePolicyType resolvePolicyRef(String oid, ExecutionContext context, OperationResult result)
throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException,
ConfigurationException, ExpressionEvaluationException {
return modelService.getObject(ValuePolicyType.class,
oid, null, context.getTask(), result).asObjectable();
}
}
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed 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 com.evolveum.midpoint.model.impl.scripting.expressions;

import com.evolveum.midpoint.model.api.PipelineItem;
import com.evolveum.midpoint.model.api.ScriptExecutionException;
import com.evolveum.midpoint.model.impl.scripting.ExecutionContext;
import com.evolveum.midpoint.model.impl.scripting.PipelineData;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.FilterContentExpressionType;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
* @author mederly
*/
@Component
public class FilterContentEvaluator extends BaseExpressionEvaluator {

public PipelineData evaluate(FilterContentExpressionType expression, PipelineData input, ExecutionContext context, OperationResult result) throws ScriptExecutionException {
List<ItemPath> keep = convert(expression.getKeep());
List<ItemPath> remove = convert(expression.getRemove());
if (keep.isEmpty() && remove.isEmpty()) {
return input; // nothing to do here
}
for (PipelineItem pipelineItem : input.getData()) {
PrismValue value = pipelineItem.getValue();
if (!(value instanceof PrismContainerValue)) {
throw new ScriptExecutionException(
"In 'select' commands in keep/remove mode, we can act only on prism container values, not on " + value);
}
PrismContainerValue<?> pcv = (PrismContainerValue) value;
if (!keep.isEmpty()) {
pcv.keepPaths(keep);
} else {
pcv.removePaths(remove);
}
}
return input;
}

private List<ItemPath> convert(List<ItemPathType> paths) {
return paths.stream().map(p -> p.getItemPath()).collect(Collectors.toList());
}

}
Expand Up @@ -21,16 +21,13 @@
import com.evolveum.midpoint.model.impl.scripting.ExecutionContext;
import com.evolveum.midpoint.model.impl.scripting.PipelineData;
import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.SelectExpressionType;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
* @author mederly
Expand All @@ -39,52 +36,25 @@
public class SelectEvaluator extends BaseExpressionEvaluator {

public PipelineData evaluate(SelectExpressionType selectExpression, PipelineData input, ExecutionContext context, OperationResult result) throws ScriptExecutionException {
if (selectExpression.getPath() != null) {
return executeSubItemSelection(input, selectExpression.getPath().getItemPath());
}
List<ItemPath> keep = convert(selectExpression.getKeep());
List<ItemPath> remove = convert(selectExpression.getRemove());
if (keep.isEmpty() && remove.isEmpty()) {
return input; // nothing to do here
}
for (PipelineItem pipelineItem : input.getData()) {
PrismValue value = pipelineItem.getValue();
if (!(value instanceof PrismContainerValue)) {
throw new ScriptExecutionException(
"In 'select' commands in keep/remove mode, we can act only on prism container values, not on " + value);
}
PrismContainerValue<?> pcv = (PrismContainerValue) value;
if (!keep.isEmpty()) {
pcv.keepPaths(keep);
} else {
pcv.removePaths(remove);
}
}
return input;
}

private List<ItemPath> convert(List<ItemPathType> paths) {
return paths.stream().map(p -> p.getItemPath()).collect(Collectors.toList());
}

private PipelineData executeSubItemSelection(PipelineData input, ItemPath path)
throws ScriptExecutionException {
PipelineData output = PipelineData.createEmpty();
for (PipelineItem item : input.getData()) {
if (selectExpression.getPath() == null) {
return input;
}
ItemPath path = selectExpression.getPath().getItemPath();
PipelineData output = PipelineData.createEmpty();
for (PipelineItem item : input.getData()) {
Object o = item.getValue().find(path);
if (o != null) {
if (o instanceof Item) {
List<? extends PrismValue> values = ((Item<? extends PrismValue, ?>) o).getValues();
values.forEach((v) -> output.addValue(v,
item.getResult().clone())); // clone to avoid aggregating subresults into unrelated results
values.forEach((v) ->
output.addValue(v, item.getResult().clone())); // clone to avoid aggregating subresults into unrelated results
} else {
throw new ScriptExecutionException(
"In 'select' commands, only property/container/reference selection is supported for now. Select on '"
+ path + "' returned this instead: " + o);
}
}
}
return output;
}

return output;
}
}
Expand Up @@ -23,8 +23,8 @@
<s:action>
<s:type>generate-password</s:type>
</s:action>
<s:select>
<s:filterContent>
<s:keep>name</s:keep>
<s:keep>credentials/password/value</s:keep>
</s:select>
</s:filterContent>
</s:pipeline>

0 comments on commit 2aa3a27

Please sign in to comment.