mirror of
https://github.com/sartography/cr-connect-workflow.git
synced 2025-02-20 11:48:16 +00:00
Modifications to the ldap scripts to bring them back in line with what Kelly is doing with the evaluation process.
This commit is contained in:
parent
a6ec0c92c7
commit
9704cbcb26
2
Pipfile
2
Pipfile
@ -38,7 +38,7 @@ recommonmark = "*"
|
||||
requests = "*"
|
||||
sentry-sdk = {extras = ["flask"],version = "==0.14.4"}
|
||||
sphinx = "*"
|
||||
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "master"}
|
||||
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "cr-connect-106-augment-eval"}
|
||||
#spiffworkflow = {editable = true,path="/home/kelly/sartography/SpiffWorkflow/"}
|
||||
swagger-ui-bundle = "*"
|
||||
webtest = "*"
|
||||
|
4
Pipfile.lock
generated
4
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "381d29428eb328ad6167774b510b9d818bd1505b95f50454a19f1564782326cc"
|
||||
"sha256": "afb6a541d1a9f33155f91529ad961492dceded89466aa1e02fed9901ac5eb146"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -804,7 +804,7 @@
|
||||
},
|
||||
"spiffworkflow": {
|
||||
"git": "https://github.com/sartography/SpiffWorkflow.git",
|
||||
"ref": "11ad40bbcb0fbd3c5bc1078e4989dc38b749f7f3"
|
||||
"ref": "7712830665b4419df019413ac095cb0749adb346"
|
||||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
|
50
crc/scripts/ldap.py
Normal file
50
crc/scripts/ldap.py
Normal file
@ -0,0 +1,50 @@
|
||||
import copy
|
||||
|
||||
from crc import app
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.ldap_service import LdapService
|
||||
|
||||
|
||||
class Ldap(Script):
|
||||
"""This Script allows to be introduced as part of a workflow and called from there, taking
|
||||
a UID (or several) as input and looking it up through LDAP to return the person's details """
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
Attempts to create a dictionary with person details, using the
|
||||
provided argument (a UID) and look it up through LDAP.
|
||||
|
||||
Examples:
|
||||
supervisor_info = ldap(supervisor_uid) // Sets the supervisor information to ldap details for the given uid.
|
||||
"""
|
||||
|
||||
def do_task_validate_only(self, task, *args, **kwargs):
|
||||
return self.set_users_info_in_task(task, args)
|
||||
|
||||
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
|
||||
return self.set_users_info_in_task(task, args)
|
||||
|
||||
def set_users_info_in_task(self, task, args):
|
||||
if len(args) != 1:
|
||||
raise ApiError(code="missing_argument",
|
||||
message="Ldap takes a single argument, the "
|
||||
"UID for the person we want to look up")
|
||||
uid = args[0]
|
||||
user_info_dict = {}
|
||||
|
||||
user_info = LdapService.user_info(uid)
|
||||
user_info_dict = {
|
||||
"display_name": user_info.display_name,
|
||||
"given_name": user_info.given_name,
|
||||
"email_address": user_info.email_address,
|
||||
"telephone_number": user_info.telephone_number,
|
||||
"title": user_info.title,
|
||||
"department": user_info.department,
|
||||
"affiliation": user_info.affiliation,
|
||||
"sponsor_type": user_info.sponsor_type,
|
||||
"uid": user_info.uid,
|
||||
"proper_name": user_info.proper_name()
|
||||
}
|
||||
|
||||
return user_info_dict
|
@ -1,78 +0,0 @@
|
||||
import copy
|
||||
|
||||
from crc import app
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.ldap_service import LdapService
|
||||
|
||||
|
||||
USER_DETAILS = {
|
||||
"PIComputingID": {
|
||||
"value": "",
|
||||
"data": {
|
||||
},
|
||||
"label": "invalid uid"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LdapLookup(Script):
|
||||
"""This Script allows to be introduced as part of a workflow and called from there, taking
|
||||
a UID as input and looking it up through LDAP to return the person's details """
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
Attempts to create a dictionary with person details, using the
|
||||
provided argument (a UID) and look it up through LDAP.
|
||||
|
||||
Example:
|
||||
LdapLookup PIComputingID
|
||||
"""
|
||||
|
||||
def do_task_validate_only(self, task, *args, **kwargs):
|
||||
self.get_user_info(task, args)
|
||||
|
||||
def do_task(self, task, *args, **kwargs):
|
||||
args = [arg for arg in args if type(arg) == str]
|
||||
user_info = self.get_user_info(task, args)
|
||||
|
||||
user_details = copy.deepcopy(USER_DETAILS)
|
||||
user_details['PIComputingID']['value'] = user_info['uid']
|
||||
if len(user_info.keys()) > 1:
|
||||
user_details['PIComputingID']['label'] = user_info.pop('label')
|
||||
else:
|
||||
user_info.pop('uid')
|
||||
user_details['PIComputingID']['data'] = user_info
|
||||
return user_details
|
||||
|
||||
def get_user_info(self, task, args):
|
||||
if len(args) < 1:
|
||||
raise ApiError(code="missing_argument",
|
||||
message="Ldap lookup script requires one argument. The "
|
||||
"UID for the person we want to look up")
|
||||
|
||||
arg = args.pop() # Extracting only one value for now
|
||||
uid = task.workflow.script_engine.evaluate_expression(task, arg)
|
||||
if not isinstance(uid, str):
|
||||
raise ApiError(code="invalid_argument",
|
||||
message="Ldap lookup script requires one 1 UID argument, of type string.")
|
||||
user_info_dict = {}
|
||||
try:
|
||||
user_info = LdapService.user_info(uid)
|
||||
user_info_dict = {
|
||||
"display_name": user_info.display_name,
|
||||
"given_name": user_info.given_name,
|
||||
"email_address": user_info.email_address,
|
||||
"telephone_number": user_info.telephone_number,
|
||||
"title": user_info.title,
|
||||
"department": user_info.department,
|
||||
"affiliation": user_info.affiliation,
|
||||
"sponsor_type": user_info.sponsor_type,
|
||||
"uid": user_info.uid,
|
||||
"label": user_info.proper_name()
|
||||
}
|
||||
except:
|
||||
user_info_dict['uid'] = uid
|
||||
app.logger.error(f'Ldap lookup failed for UID {uid}')
|
||||
|
||||
return user_info_dict
|
@ -1,60 +0,0 @@
|
||||
import copy
|
||||
|
||||
from crc import app
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.ldap_service import LdapService
|
||||
|
||||
|
||||
class LdapReplace(Script):
|
||||
"""This Script allows to be introduced as part of a workflow and called from there, taking
|
||||
a UID (or several) as input and looking it up through LDAP to return the person's details """
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
Attempts to create a dictionary with person details, using the
|
||||
provided argument (a UID) and look it up through LDAP.
|
||||
|
||||
Examples:
|
||||
#! LdapReplace supervisor
|
||||
#! LdapReplace supervisor collaborator
|
||||
#! LdapReplace supervisor cosupervisor collaborator
|
||||
"""
|
||||
|
||||
def do_task_validate_only(self, task, *args, **kwargs):
|
||||
self.set_users_info_in_task(task, args)
|
||||
|
||||
def do_task(self, task, *args, **kwargs):
|
||||
args = [arg for arg in args if type(arg) == str]
|
||||
self.set_users_info_in_task(task, args)
|
||||
|
||||
def set_users_info_in_task(self, task, args):
|
||||
if len(args) < 1:
|
||||
raise ApiError(code="missing_argument",
|
||||
message="Ldap replace script requires at least one argument. The "
|
||||
"UID for the person(s) we want to look up")
|
||||
|
||||
users_info = {}
|
||||
for arg in args:
|
||||
uid = task.workflow.script_engine.evaluate_expression(task, arg)
|
||||
if not isinstance(uid, str):
|
||||
raise ApiError(code="invalid_argument",
|
||||
message="Ldap replace script found an invalid argument, type string is required")
|
||||
user_info_dict = {}
|
||||
try:
|
||||
user_info = LdapService.user_info(uid)
|
||||
user_info_dict = {
|
||||
"display_name": user_info.display_name,
|
||||
"given_name": user_info.given_name,
|
||||
"email_address": user_info.email_address,
|
||||
"telephone_number": user_info.telephone_number,
|
||||
"title": user_info.title,
|
||||
"department": user_info.department,
|
||||
"affiliation": user_info.affiliation,
|
||||
"sponsor_type": user_info.sponsor_type,
|
||||
"uid": user_info.uid,
|
||||
"proper_name": user_info.proper_name()
|
||||
}
|
||||
except:
|
||||
app.logger.error(f'Ldap replace failed for UID {uid}')
|
||||
task.data[arg] = user_info_dict
|
@ -29,19 +29,11 @@ from crc import app
|
||||
|
||||
class CustomBpmnScriptEngine(BpmnScriptEngine):
|
||||
"""This is a custom script processor that can be easily injected into Spiff Workflow.
|
||||
Rather than execute arbitrary code, this assumes the script references a fully qualified python class
|
||||
such as myapp.RandomFact. """
|
||||
It will execute python code read in from the bpmn. It will also make any scripts in the
|
||||
scripts directory available for execution. """
|
||||
|
||||
def execute(self, task: SpiffTask, script, data):
|
||||
"""
|
||||
Functions in two modes.
|
||||
1. If the command is proceeded by #! then this is assumed to be a python script, and will
|
||||
attempt to load that python module and execute the do_task method on that script. Scripts
|
||||
must be located in the scripts package and they must extend the script.py class.
|
||||
2. If not proceeded by the #! this will attempt to execute the script directly and assumes it is
|
||||
valid Python.
|
||||
"""
|
||||
# Shlex splits the whole string while respecting double quoted strings within
|
||||
|
||||
study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
|
||||
if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
|
||||
workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
|
||||
|
@ -10,7 +10,8 @@
|
||||
<bpmn:scriptTask id="Activity_0s5v97n" name="Ldap Replace">
|
||||
<bpmn:incoming>Flow_08n2npe</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1xlrgne</bpmn:outgoing>
|
||||
<bpmn:script>#! LdapReplace Supervisor Investigator</bpmn:script>
|
||||
<bpmn:script>Supervisor = ldap(Supervisor)
|
||||
Investigator = ldap(Investigator)</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_1synsig" sourceRef="StartEvent_1" targetRef="Activity_1l9vih3" />
|
||||
<bpmn:sequenceFlow id="Flow_1xlrgne" sourceRef="Activity_0s5v97n" targetRef="Activity_0f78ek5" />
|
||||
@ -33,6 +34,10 @@
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0tad5ma">
|
||||
<bpmndi:BPMNEdge id="Flow_11e7jgz_di" bpmnElement="Flow_11e7jgz">
|
||||
<di:waypoint x="720" y="117" />
|
||||
<di:waypoint x="802" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_08n2npe_di" bpmnElement="Flow_08n2npe">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="450" y="117" />
|
||||
@ -45,22 +50,18 @@
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="270" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_11e7jgz_di" bpmnElement="Flow_11e7jgz">
|
||||
<di:waypoint x="720" y="117" />
|
||||
<di:waypoint x="802" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0izrcj4_di" bpmnElement="Event_0izrcj4">
|
||||
<dc:Bounds x="802" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_04imfm6_di" bpmnElement="Activity_0s5v97n">
|
||||
<dc:Bounds x="450" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0xugr62_di" bpmnElement="Activity_1l9vih3">
|
||||
<dc:Bounds x="270" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0izrcj4_di" bpmnElement="Event_0izrcj4">
|
||||
<dc:Bounds x="802" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_17h05g6_di" bpmnElement="Activity_0f78ek5">
|
||||
<dc:Bounds x="620" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
|
@ -1,7 +1,8 @@
|
||||
from tests.base_test import BaseTest
|
||||
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
from crc.scripts.ldap_replace import LdapReplace
|
||||
from crc.scripts.ldap import Ldap
|
||||
from crc.api.common import ApiError
|
||||
from crc import db, mail
|
||||
|
||||
|
||||
@ -14,60 +15,19 @@ class TestLdapLookupScript(BaseTest):
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
|
||||
task.data = {
|
||||
'PIComputingID': 'dhf8r'
|
||||
}
|
||||
script = Ldap()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "dhf8r")
|
||||
|
||||
script = LdapReplace()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
|
||||
|
||||
self.assertEqual(task.data['PIComputingID']['display_name'], 'Dan Funk')
|
||||
self.assertEqual(task.data['PIComputingID']['given_name'], 'Dan')
|
||||
self.assertEqual(task.data['PIComputingID']['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(task.data['PIComputingID']['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(task.data['PIComputingID']['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(task.data['PIComputingID']['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(task.data['PIComputingID']['affiliation'], 'faculty')
|
||||
self.assertEqual(task.data['PIComputingID']['sponsor_type'], 'Staff')
|
||||
self.assertEqual(task.data['PIComputingID']['uid'], 'dhf8r')
|
||||
self.assertEqual(task.data['PIComputingID']['proper_name'], 'Dan Funk - (dhf8r)')
|
||||
|
||||
def test_get_existing_users_details(self):
|
||||
self.load_example_data()
|
||||
self.create_reference_document()
|
||||
workflow = self.create_workflow('empty_workflow')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
|
||||
task.data = {
|
||||
'supervisor': 'dhf8r',
|
||||
'investigator': 'lb3dp'
|
||||
}
|
||||
|
||||
script = LdapReplace()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "supervisor", "investigator")
|
||||
|
||||
self.assertEqual(task.data['supervisor']['display_name'], 'Dan Funk')
|
||||
self.assertEqual(task.data['supervisor']['given_name'], 'Dan')
|
||||
self.assertEqual(task.data['supervisor']['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(task.data['supervisor']['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(task.data['supervisor']['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(task.data['supervisor']['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(task.data['supervisor']['affiliation'], 'faculty')
|
||||
self.assertEqual(task.data['supervisor']['sponsor_type'], 'Staff')
|
||||
self.assertEqual(task.data['supervisor']['uid'], 'dhf8r')
|
||||
self.assertEqual(task.data['supervisor']['proper_name'], 'Dan Funk - (dhf8r)')
|
||||
|
||||
self.assertEqual(task.data['investigator']['display_name'], 'Laura Barnes')
|
||||
self.assertEqual(task.data['investigator']['given_name'], 'Laura')
|
||||
self.assertEqual(task.data['investigator']['email_address'], 'lb3dp@virginia.edu')
|
||||
self.assertEqual(task.data['investigator']['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(task.data['investigator']['title'], 'E0:Associate Professor of Systems and Information Engineering')
|
||||
self.assertEqual(task.data['investigator']['department'], 'E0:EN-Eng Sys and Environment')
|
||||
self.assertEqual(task.data['investigator']['affiliation'], 'faculty')
|
||||
self.assertEqual(task.data['investigator']['sponsor_type'], 'Staff')
|
||||
self.assertEqual(task.data['investigator']['uid'], 'lb3dp')
|
||||
self.assertEqual(task.data['investigator']['proper_name'], 'Laura Barnes - (lb3dp)')
|
||||
self.assertEqual(user_details['display_name'], 'Dan Funk')
|
||||
self.assertEqual(user_details['given_name'], 'Dan')
|
||||
self.assertEqual(user_details['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(user_details['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(user_details['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(user_details['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(user_details['affiliation'], 'faculty')
|
||||
self.assertEqual(user_details['sponsor_type'], 'Staff')
|
||||
self.assertEqual(user_details['uid'], 'dhf8r')
|
||||
self.assertEqual(user_details['proper_name'], 'Dan Funk - (dhf8r)')
|
||||
|
||||
def test_get_invalid_user_details(self):
|
||||
self.load_example_data()
|
||||
@ -80,10 +40,10 @@ class TestLdapLookupScript(BaseTest):
|
||||
'PIComputingID': 'rec3z'
|
||||
}
|
||||
|
||||
script = LdapReplace()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
|
||||
script = Ldap()
|
||||
with(self.assertRaises(ApiError)):
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
|
||||
|
||||
self.assertEqual(task.data['PIComputingID'], {})
|
||||
|
||||
def test_bpmn_task_receives_user_details(self):
|
||||
workflow = self.create_workflow('ldap_replace')
|
||||
|
Loading…
x
Reference in New Issue
Block a user