Page tree
Skip to end of metadata
Go to start of metadata

Business description

To secure cost process, our company decide to block possibility to see issues by unauthorized employees. An access to them will be related to department and cost center or cost group and cost category.

Solution Brief

Using decision tables we will calculate, which group is authorized and set them to the custom field. Final validation will be done based on that data.

To solve that, we prepare two decision tables - each one will return a list of group based on related parameters.

Example Decision Table

Script

Note

In this script we use some superclasses, which help us in code management. For more information, see Usage of base groovy classes and utilities page.

import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import eu.rivetgroup.atlas.jira.fields.api.exceptions.ExceptionHandlingMode
import global.fields.CustomFieldCode
import global.fields.FieldUtils

@WithPlugin([
		"eu.rivetgroup.atlas.rvg-jira-app-base-plugin",
		"eu.rivetgroup.atlas.rvg-jira-decision-tables-plugin"
])
class TestSetAccessDataPostFunction extends BaseDecisionTablePostFunction {

	TestSetAccessDataPostFunction(Map<String, Object> transientVars, boolean validatorMode) {
		super(transientVars, validatorMode, false)
	}

	@Override
	protected boolean executeInternal() {
		def departmentField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.DEPARTMENT_CF))
		def costCentreField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.COST_CENTRE))

		def costGroupField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.COST_GROUP))
		def costCategoryField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.COST_CATEGORY))

		def groupAssigneeField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.GROUP_ASSIGNEE))
		def accessibleForGroupsField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.ACCESSIBLE_FOR_GROUPS))

		accessibleForGroupsField.config.exceptionHandlingStrategy.globalCheckStrategy
				.setSourceHandlingMode(ExceptionHandlingMode.REGISTER)
				.setRegistryHandlingMode(ExceptionHandlingMode.LOG_WARNING)

		issueFieldOperator.config.setUseTransientFieldValues(true)

		accessibleForGroupsField.setObjectValue(null)

		accessibleForGroupsField.appendValue(groupAssigneeField.getValue().multi())

		def dtCostCentreResult = decisionTableManager.getDMNDecisionTableOperations(
				"costAccess",
				"costCentreAccess"
		).executeQuery([
				"department": departmentField.getBusinessKey().first(),
				"costCentre": costCentreField.getBusinessKey().first()
		])


		issueFieldOperator.getConfig().setCurrentExecutionInfo(dtCostCentreResult.executionContextInfo)

		def groupNames = dtCostCentreResult.multiNonNull().collect({elem -> elem.get("accessibleForGroups")})

		accessibleForGroupsField.appendValue(accessibleForGroupsField.getValueByBusinessKey(groupNames))

		def dtCategoryResult = decisionTableManager.getDMNDecisionTableOperations(
				"costAccess",
				"costCategoryAccess"
		).executeQuery([
				"costGroup": costGroupField.getBusinessKey().first(),
				"costCategory": costCategoryField.getBusinessKey().first()
		])
		issueFieldOperator.getConfig().setCurrentExecutionInfo(dtCategoryResult.executionContextInfo)

		groupNames = dtCategoryResult.multiNonNull().collect({elem -> elem.get("accessibleForGroups")})

		accessibleForGroupsField.appendValue(accessibleForGroupsField.getValueByBusinessKey(groupNames))
		return true;
	}
}

Explanation

@WithPlugin([
	"eu.rivetgroup.atlas.rvg-jira-app-base-plugin",
	"eu.rivetgroup.atlas.rvg-jira-decision-tables-plugin"
])
class TestSetAccessDataPostFunction extends BaseDecisionTablePostFunction {

TestSetAccessDataPostFunction(Map<String, Object> transientVars, boolean validatorMode) {
	super(transientVars, validatorMode, false)
}

Traditionally, we start with import functionalities and declare a constructor.

def departmentField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.DEPARTMENT_CF))
def costCentreField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.COST_CENTRE))

def costGroupField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.COST_GROUP))
def costCategoryField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.COST_CATEGORY))

def groupAssigneeField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.GROUP_ASSIGNEE))
def accessibleForGroupsField = issueFieldOperator.forField(FieldUtils.getCustomField(CustomFieldCode.ACCESSIBLE_FOR_GROUPS))

Next step is get references to necessary fields.

accessibleForGroupsField.config.exceptionHandlingStrategy.globalCheckStrategy
				.setSourceHandlingMode(ExceptionHandlingMode.REGISTER)
				.setRegistryHandlingMode(ExceptionHandlingMode.LOG_WARNING)

This time we want to register possible errors - for example non existing group. In that situation terminate operation is unnecessary, but we would like to log them, just in case.

issueFieldOperator.config.setUseTransientFieldValues(true)

 We are going to combine results from two decision tables and the current group assignee if it exists. We will do this using transient variables, thanks to them all changes is made on variables and that does not interfere with change history.

accessibleForGroupsField.setObjectValue(null)
accessibleForGroupsField.appendValue(groupAssigneeField.getValue().multi())

Operations is started with clear field value and set there current assigned group.

def dtCostCentreResult = decisionTableManager.getDMNDecisionTableOperations(
	"costAccess",
	"costCentreAccess"
).executeQuery([
	"department": departmentField.getBusinessKey().first(),
	"costCentre": costCentreField.getBusinessKey().first()
])
issueFieldOperator.getConfig().setCurrentExecutionInfo(dtCostCentreResult.executionContextInfo)

We get possibilities from first decision table.

def groupNames = dtCostCentreResult.multiNonNull().collect({elem -> elem.get("accessibleForGroups")})
accessibleForGroupsField.appendValue(accessibleForGroupsField.getValueByBusinessKey(groupNames))

And add them to such field values.

def dtCategoryResult = decisionTableManager.getDMNDecisionTableOperations(
	"costAccess",
	"costCategoryAccess"
).executeQuery([
	"costGroup": costGroupField.getBusinessKey().first(),
	"costCategory": costCategoryField.getBusinessKey().first()
])

issueFieldOperator.getConfig().setCurrentExecutionInfo(dtCategoryResult.executionContextInfo)
groupNames = dtCategoryResult.multiNonNull().collect({elem -> elem.get("accessibleForGroups")})
accessibleForGroupsField.appendValue(accessibleForGroupsField.getValueByBusinessKey(groupNames))

Analogously, we add values calculated by second decision tables.

Attachments

TestSetAccessDataPostFunction.groovycostAccess.dmn

  • No labels