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:
Dan Funk 2020-07-30 13:35:20 -04:00
parent a6ec0c92c7
commit 9704cbcb26
8 changed files with 82 additions and 217 deletions

View File

@ -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
View File

@ -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
View 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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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>

View File

@ -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')