Skip to content

Commit 0ca4889

Browse files
committed
Add get form-variables command security option
1 parent cf263c7 commit 0ca4889

File tree

7 files changed

+151
-29
lines changed

7 files changed

+151
-29
lines changed

bpmn/MyUT1.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@
7070
"tableView": true,
7171
"key": "comments",
7272
"type": "textarea",
73-
"input": true
73+
"input": true,
74+
"properties": {
75+
"camVariableName": "postProcessed_submission.data.thisIsAExpectedErrorToDemoDefaultValueErrors"
76+
}
7477
},
7578
{
7679
"type": "button",

bpmn/SomeProcess1.bpmn

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
</camunda:validation>
2020
</camunda:formField>
2121
</camunda:formData>
22+
<camunda:properties>
23+
<camunda:property name="restricted-variables" value="neverSeeVar" />
24+
</camunda:properties>
2225
</bpmn:extensionElements>
2326
<bpmn:incoming>Flow_0069xxd</bpmn:incoming>
2427
<bpmn:outgoing>Flow_18xtnen</bpmn:outgoing>
@@ -37,7 +40,9 @@
3740
<bpmn:incoming>Flow_1ax32ut</bpmn:incoming>
3841
<bpmn:outgoing>Flow_0eob9zj</bpmn:outgoing>
3942
<bpmn:script>var hasSubmission = execution.hasVariable("submission")
40-
execution.setVariable('postProcessed_submission', execution.getVariable('submission'))</bpmn:script>
43+
execution.setVariable('postProcessed_submission', execution.getVariable('submission'))
44+
45+
execution.setVariable('neverSeeVar', 'this variable should never be returned on the Typical Form with Service Validation task as it is restricted in the extension properties')</bpmn:script>
4146
</bpmn:scriptTask>
4247
<bpmn:sequenceFlow id="Flow_0069xxd" sourceRef="Gateway_0u22n92" targetRef="Activity_1xq7c62" />
4348
<bpmn:sequenceFlow id="Flow_0vjjadb" sourceRef="Gateway_0u22n92" targetRef="Activity_16j3pe3" />
@@ -156,9 +161,15 @@ execution.setVariable('postProcessed_submission', execution.getVariable('submiss
156161
<bpmn:escalation id="Escalation_07acmmp" name="custom-escalation" escalationCode="ce1" />
157162
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
158163
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="someProcess1">
159-
<bpmndi:BPMNShape id="TextAnnotation_19wn5bt_di" bpmnElement="TextAnnotation_19wn5bt">
160-
<dc:Bounds x="210" y="450" width="140" height="82" />
161-
</bpmndi:BPMNShape>
164+
<bpmndi:BPMNEdge id="Flow_0dsu483_di" bpmnElement="Flow_0dsu483">
165+
<di:waypoint x="590" y="120" />
166+
<di:waypoint x="622" y="120" />
167+
</bpmndi:BPMNEdge>
168+
<bpmndi:BPMNEdge id="Flow_1623iq8_di" bpmnElement="Flow_1623iq8">
169+
<di:waypoint x="440" y="595" />
170+
<di:waypoint x="440" y="120" />
171+
<di:waypoint x="490" y="120" />
172+
</bpmndi:BPMNEdge>
162173
<bpmndi:BPMNEdge id="Flow_1ius0d1_di" bpmnElement="Flow_1ius0d1">
163174
<di:waypoint x="760" y="630" />
164175
<di:waypoint x="812" y="630" />
@@ -257,15 +268,6 @@ execution.setVariable('postProcessed_submission', execution.getVariable('submiss
257268
<di:waypoint x="188" y="620" />
258269
<di:waypoint x="240" y="620" />
259270
</bpmndi:BPMNEdge>
260-
<bpmndi:BPMNEdge id="Flow_1623iq8_di" bpmnElement="Flow_1623iq8">
261-
<di:waypoint x="440" y="595" />
262-
<di:waypoint x="440" y="120" />
263-
<di:waypoint x="490" y="120" />
264-
</bpmndi:BPMNEdge>
265-
<bpmndi:BPMNEdge id="Flow_0dsu483_di" bpmnElement="Flow_0dsu483">
266-
<di:waypoint x="590" y="120" />
267-
<di:waypoint x="622" y="120" />
268-
</bpmndi:BPMNEdge>
269271
<bpmndi:BPMNShape id="Event_0emfvgy_di" bpmnElement="Event_0emfvgy">
270272
<dc:Bounds x="152" y="602" width="36" height="36" />
271273
</bpmndi:BPMNShape>
@@ -338,10 +340,9 @@ execution.setVariable('postProcessed_submission', execution.getVariable('submiss
338340
<bpmndi:BPMNShape id="Activity_188iga8_di" bpmnElement="Activity_0ngrvxl">
339341
<dc:Bounds x="490" y="80" width="100" height="80" />
340342
</bpmndi:BPMNShape>
341-
<bpmndi:BPMNEdge id="Association_04d5fx0_di" bpmnElement="Association_04d5fx0">
342-
<di:waypoint x="287" y="580" />
343-
<di:waypoint x="283" y="532" />
344-
</bpmndi:BPMNEdge>
343+
<bpmndi:BPMNShape id="TextAnnotation_19wn5bt_di" bpmnElement="TextAnnotation_19wn5bt">
344+
<dc:Bounds x="210" y="450" width="140" height="82" />
345+
</bpmndi:BPMNShape>
345346
<bpmndi:BPMNShape id="Event_1p2gfns_di" bpmnElement="Event_1ugcuo2">
346347
<dc:Bounds x="572" y="692" width="36" height="36" />
347348
</bpmndi:BPMNShape>
@@ -351,6 +352,10 @@ execution.setVariable('postProcessed_submission', execution.getVariable('submiss
351352
<bpmndi:BPMNShape id="Event_0rfidvh_di" bpmnElement="Event_19kscew">
352353
<dc:Bounds x="472" y="772" width="36" height="36" />
353354
</bpmndi:BPMNShape>
355+
<bpmndi:BPMNEdge id="Association_04d5fx0_di" bpmnElement="Association_04d5fx0">
356+
<di:waypoint x="287" y="580" />
357+
<di:waypoint x="283" y="532" />
358+
</bpmndi:BPMNEdge>
354359
</bpmndi:BPMNPlane>
355360
</bpmndi:BPMNDiagram>
356361
</bpmn:definitions>

common/forms/formio.html

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
if (formLocDeployment() === false && formLocPath() === false) {
105105
//@TODO bubble this to formio errors
106106
console.error("No valid form json location was found for formio. (could not deployment or path params in form key)")
107+
showNotification('error', 5000, "Invalid Form JSON", "No valid form json location was found for formio. (could not deployment or path params in form key)")
107108
}
108109

109110
let formName = formLocDeployment() === true ? formNameDeployment : formNamePath
@@ -119,6 +120,7 @@
119120

120121
if (formResource === undefined) {
121122
console.error('Unable to find resource with name: ' + details.formName);
123+
showNotification('error', 5000, "Cannot find resource", "Unable to load form: unable to find resource in deployment with name " + details.formName)
122124
}
123125

124126
return {deploymentId: details.deploymentId, resourceId: formResource.id}
@@ -138,6 +140,7 @@
138140

139141
} else {
140142
console.error("Unknown form type was provided: " + details.formType)
143+
showNotification('error', 5000, "Unknown Form Type", "Unable to load form: unknown form type was provided: " + details.formType)
141144
}
142145
});
143146
}]);
@@ -155,20 +158,27 @@
155158
let variables = {}
156159
let promises = []
157160

158-
_.forEach(varNames, function (varName) {
159-
if (!variables.hasOwnProperty(varName)) {
160-
let promise = $http.get(Uri.appUri('engine://engine/:engine/task/' + taskId + '/variables/' + varName), {params: {deserializeValue: false}})
161+
// _.forEach(varNames, function (varName) {
162+
// if (!variables.hasOwnProperty(varName)) {
163+
let promise = $http.get(Uri.appUri('engine://engine/:engine/task/' + taskId + '/form-variables/'), {
164+
params: {
165+
deserializeValues: false,
166+
variableNames: varNames.join(",")
167+
}
168+
})
161169
promises.push(promise)
162170
promise.then(response => {
163-
164-
if (response.data.type === 'Json') {
165-
response.data.value = JSON.parse(response.data.value)
166-
}
167-
variables[varName] = response.data.value
171+
_.forOwn(response.data, function(value, key) {
172+
if (value.type === 'Json') {
173+
value.value = JSON.parse(value.value)
174+
}
175+
variables[key] = value.value
176+
} );
177+
// variables = response.data
168178
})
169-
}
179+
// }
170180

171-
})
181+
// })
172182
Promise.all(promises).then(function () {
173183
resolve(variables)
174184
})
@@ -180,6 +190,17 @@
180190
})
181191
}
182192

193+
function showNotification(type, duration, status, message){
194+
inject(['Notifications', function(Notifications) {
195+
Notifications.addMessage({
196+
type: type,
197+
duration: duration,
198+
status: status,
199+
message: message
200+
});
201+
}]);
202+
}
203+
183204
function getDefaultValues(variablesStore, submissionObject, schema){
184205
let defaultValues = {data: {}}
185206
FormioUtils.eachComponent(schema.components, component => {
@@ -188,6 +209,12 @@
188209
let defaultValue = _.get(variablesStore, component.properties[camVariableNameKey])
189210
let key = component.key
190211

212+
// @TODO review how to make this appear more quickly
213+
if (defaultValue === undefined){
214+
showNotification('error', null, 'Unable to find default value in variables',
215+
'form-variables data did not return expected default value in variables in key ' + component.properties[camVariableNameKey] )
216+
}
217+
191218
if (component.properties[stringifyKey] === 'true'){
192219
// @TODO do a check if the value is a object!
193220
defaultValue = JSON.stringify(defaultValue)

docker/bpm-platform.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
<plugin>
3939
<class>com.github.stephenott.camunda.formio.FormioFormFieldValidatorProcessEnginePlugin</class>
4040
</plugin>
41+
<plugin>
42+
<class>com.github.stephenott.camunda.tasks.forms.command.GetFormVariablesSecurityProcessEnginePlugin</class>
43+
</plugin>
44+
4145

4246
<!-- LDAP CONFIGURATION -->
4347
<!-- Uncomment this section in order to enable LDAP support for this process engine -->
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.github.stephenott.camunda.tasks.forms.command
2+
3+
import org.camunda.bpm.engine.impl.cmd.GetTaskFormVariablesCmd
4+
import org.camunda.bpm.engine.impl.interceptor.CommandContext
5+
import org.camunda.bpm.engine.variable.VariableMap
6+
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaProperties
7+
8+
class CustomGetTaskFormVariablesCmd(taskId: String, variableNames: MutableCollection<String>?, deserializeObjectValues: Boolean) : GetTaskFormVariablesCmd(taskId, variableNames, deserializeObjectValues) {
9+
10+
companion object {
11+
var allowedVariablesKey: String = "allowed-variables"
12+
var restrictedVariablesKey: String = "restricted-variables"
13+
}
14+
15+
override fun execute(commandContext: CommandContext): VariableMap {
16+
val result = super.execute(commandContext)
17+
18+
//@TODO add debug info about variables being filtered
19+
20+
val utModelInstance = commandContext.taskManager.findTaskById(resourceId).bpmnModelElementInstance
21+
val props = utModelInstance.extensionElements.elementsQuery.filterByType<CamundaProperties>(CamundaProperties::class.java).singleResult()
22+
val allowedVars = props.camundaProperties.find {
23+
it.camundaName == allowedVariablesKey
24+
}
25+
26+
val restrictedVars = props.camundaProperties.find {
27+
it.camundaName == restrictedVariablesKey
28+
}
29+
30+
allowedVars?.let { camProp ->
31+
val varNames = camProp.camundaValue.split(",").map { it.trim() }
32+
result.entries.removeIf {
33+
it.key !in varNames
34+
}
35+
}
36+
37+
restrictedVars?.let { camProp->
38+
val varNames = camProp.camundaValue.split(",").map { it.trim() }
39+
result.entries.removeIf {
40+
it.key in varNames
41+
}
42+
}
43+
44+
return result
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.github.stephenott.camunda.tasks.forms.command
2+
3+
import org.camunda.bpm.engine.ProcessEngine
4+
import org.camunda.bpm.engine.impl.FormServiceImpl
5+
import org.camunda.bpm.engine.impl.ServiceImpl
6+
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl
7+
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin
8+
import org.camunda.bpm.engine.variable.VariableMap
9+
import kotlin.reflect.full.createInstance
10+
11+
/**
12+
* Plugin for replacing the GetTaskFormVariablesCmd with CustomGetTaskFormVariablesCmd.
13+
* The replacement provides additional security filtering based on Camunda Extension Properties configurations in the bpmn
14+
*/
15+
open class GetFormVariablesSecurityProcessEnginePlugin : ProcessEnginePlugin {
16+
17+
override fun preInit(processEngineConfiguration: ProcessEngineConfigurationImpl) {
18+
// Setup a new instance of form service that has the cmd for security filtering of variables
19+
// @TODO add startup info about form service being overriden and security added to remove variables.
20+
processEngineConfiguration.formService = object: FormServiceImpl() {
21+
override fun getTaskFormVariables(taskId: String, formVariables: MutableCollection<String>?, deserializeObjectValues: Boolean): VariableMap {
22+
return commandExecutor.execute(CustomGetTaskFormVariablesCmd(taskId, formVariables, deserializeObjectValues))
23+
}
24+
}
25+
26+
}
27+
28+
override fun postInit(processEngineConfiguration: ProcessEngineConfigurationImpl) {
29+
}
30+
31+
override fun postProcessEngineBuild(processEngine: ProcessEngine) {
32+
}
33+
}

springboot/src/main/kotlin/com/github/stephenott/camunda/formio/Application.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.stephenott.camunda.formio
22

3+
import com.github.stephenott.camunda.tasks.forms.command.GetFormVariablesSecurityProcessEnginePlugin
34
import org.camunda.bpm.spring.boot.starter.annotation.EnableProcessApplication
45
import org.springframework.boot.autoconfigure.SpringBootApplication
56
import org.springframework.boot.runApplication
@@ -12,4 +13,7 @@ class Application
1213
fun main(args: Array<String>) = runApplication<Application>(*args).let { Unit }
1314

1415
@Component
15-
class MyPlugin: FormioFormFieldValidatorProcessEnginePlugin()
16+
class MyPlugin: FormioFormFieldValidatorProcessEnginePlugin()
17+
18+
@Component
19+
class MyFormsSecurityPlugin: GetFormVariablesSecurityProcessEnginePlugin()

0 commit comments

Comments
 (0)