From 7ff2c746cd24e7439e73ac14add8bd4050022574 Mon Sep 17 00:00:00 2001
From: Aaron022 <41335946+Aaron022@users.noreply.github.com>
Date: Fri, 19 Jun 2020 18:30:16 +0800
Subject: [PATCH] Workforce connector
https://github.com/workato/connector_sdk/pull/514
Status: Merged
---
.../custom_auth/workforce_connector.rb | 1211 +++++++++++++++++
1 file changed, 1211 insertions(+)
create mode 100644 custom_connectors/custom_auth/workforce_connector.rb
diff --git a/custom_connectors/custom_auth/workforce_connector.rb b/custom_connectors/custom_auth/workforce_connector.rb
new file mode 100644
index 00000000..49973d02
--- /dev/null
+++ b/custom_connectors/custom_auth/workforce_connector.rb
@@ -0,0 +1,1211 @@
+{
+ title: 'Workforce',
+ secure_tunnel: true,
+ connection: {
+ fields: [
+ { name: 'user_name',
+ optional: false },
+ { name: 'password',
+ optional: false,
+ control_type: 'password' },
+ { name: 'base_url',
+ optional: false,
+ label: 'Host name',
+ hint: 'hint: host name, e.g. https://abc.workforcehosting.eu' }
+ ],
+ authorization: {
+ type: 'none'
+ },
+ base_uri: lambda do |connection|
+ connection['base_url']
+ end
+ },
+ test: lambda do |_|
+ true
+ end,
+ methods: {
+ build_request_fields_xml: lambda do |input|
+ details = input&.dig('detailRequest', 'details')&.map do |items|
+ {
+ 'xsd1:hours': [{
+ "content!": items['hours']
+ }],
+ 'xsd1:inTime': [{
+ 'xsd2:day': [{
+ "content!": items['inTime']&.strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": items['inTime']&.strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": items['inTime']&.strftime('%Y')
+ }],
+ 'xsd2:hours': [{
+ "content!": items['inTime']&.strftime('%H')
+ }],
+ 'xsd2:minutes': [{
+ "content!": items['inTime']&.strftime('%M')
+ }],
+ 'xsd2:seconds': [{
+ "content!": items['inTime']&.strftime('%S')
+ }]
+ }],
+ 'xsd1:outTime': [{
+ 'xsd2:day': [{
+ "content!": items['outTime']&.strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": items['outTime']&.strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": items['outTime']&.strftime('%Y')
+ }],
+ 'xsd2:hours': [{
+ "content!": items['outTime']&.strftime('%H')
+ }],
+ 'xsd2:minutes': [{
+ "content!": items['outTime']&.strftime('%M')
+ }],
+ 'xsd2:seconds': [{
+ "content!": items['outTime']&.strftime('%S')
+ }]
+ }],
+ 'xsd1:payCode': [{
+ 'xsd2:policyId': [{
+ "content!": items['payCode']
+ }]
+ }],
+ 'xsd1:workDate': [{
+ 'xsd2:day': [{
+ "content!": items['workDate']&.strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": items['workDate']&.strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": items['workDate']&.strftime('%Y')
+ }]
+ }]
+ }
+ end
+ {
+ 'xsd1:assignmentId': [{
+ 'xsd2:id': [{
+ "content!": input&.dig('detailRequest', 'assignmentId')
+ }]
+ }],
+ 'xsd1:comments': [{
+ "content!": input&.dig('detailRequest', 'comments')
+ }],
+ 'xsd1:details' => details
+ }
+ end,
+ extract_multipart_boundary: lambda do |input|
+ content_type = input.dig('content_type')
+ if not content_type.present?
+ error('Response error:Content-Type not found in HTTP response headers')
+ end
+ multipart_form_boundary = content_type.scan(/(?<=boundary=\")(.*?)(?=\")/).dig(0, 0)
+ if not multipart_form_boundary.present?
+ error('Response error:Multipart form boundary not found')
+ else
+ multipart_form_boundary
+ end
+ end,
+ generate_xml_payload: lambda do |input|
+ idc_service = input.dig(:idc_service)
+ document_element = input.dig(:document_element)
+ if not (idc_service.present? and document_element.present?)
+ error('IdcService or Document content not present')
+ end
+ {
+ "@xmlns:ns1": 'http://schemas.xmlsoap.org/soap/envelope/',
+ "ns1:Body": [{
+ "ns2:GenericRequest": [{
+ "@xmlns:ns2": 'http://www.oracle.com/UCM',
+ "@webKey": 'cs',
+ "ns2:Service": [{
+ "@IdcService": idc_service,
+ "content!": document_element
+ }]
+ }]
+ }]
+ }
+ end,
+ extract_content_headers: lambda do |input|
+ content_headers_string = input.strip.split(/^\s*$(?:\r\n?|\n)/m).dig(0)
+ if not content_headers_string.blank?
+ {
+ content_headers: content_headers_string.scan(/([\w-]+): (.*)/).map do |i|
+ {
+ key: i.dig(0),
+ value: i.dig(1)
+ }
+ end
+ }
+ end
+ end,
+ extract_content_body: lambda do |input|
+ content_body = input.strip.split(/^\s*$(?:\r\n?|\n)/m).dig(1)
+ content_body.blank? ? nil : { content_body: content_body }
+ end,
+ extract_multipart_parts: lambda do |input|
+ body = input.dig(:body)
+ multipart_form_boundary = input.dig(:multipart_form_boundary).present? ? input.dig(:multipart_form_boundary) : "--#{call(:extract_multipart_boundary, input.dig(:headers))}"
+ content_strings = body.split(multipart_form_boundary)[1..-2]
+ parts = content_strings.map do |i|
+ call(:extract_content_headers, i).merge(
+ call(:extract_content_body, i)
+ )
+ end
+ parts
+ end
+ },
+ object_definitions: {
+ submit_time_off_request: {
+ fields: lambda do |_connection, _config_fields|
+ [
+ { name: 'acknowledgments' },
+ { name: 'comments' },
+ { name: 'detailRequest', label: 'Request details', type: 'object',
+ properties: [
+ { name: 'assignmentId', type: 'integer' },
+ { name: 'caseId', type: 'integer' },
+ { name: 'comments' },
+ { name: 'details', label: 'Time off items', type: 'array', of: 'object', properties: [
+ { name: 'hours', type: 'number' },
+ { name: 'inTime', type: 'date_time' },
+ { name: 'outTime', type: 'date_time' },
+ { name: 'payCode', hint: 'The ID of the pay code for which the specific detail' \
+ ' record is entered against.' },
+ { name: 'workDate', type: 'date' }
+ ] }
+ ] },
+ { name: 'requestDateRange', type: 'object', properties: [
+ { name: 'startDate', type: 'date',
+ hint: 'The day, month, and year of the first date of the time off request.' },
+ { name: 'endDate', type: 'date',
+ hint: 'The day, month, and year of the last date of the time off request.' }
+ ] }
+ ]
+ end
+ },
+ submmit_time_off_response: {
+ fields: lambda do |_connection, _config_fields|
+ [
+ { name: 'detailedErrorMessage' },
+ { name: 'operationSuccessful' },
+ { name: 'resultCode' },
+ { name: 'resultDescription' },
+ { name: 'result', type: 'object', properties: [
+ { name: 'detailResponse', type: 'object', properties: [
+ { name: 'acknowledgments', type: 'array', of: 'object', properties: [
+ { name: 'acknowledgmentId', type: 'integer', hint: 'A configured ID for a type of acknowledgment.' },
+ { name: 'acknowledgmentLabel', hint: 'A configured, short description of the acknowledgment type.' },
+ { name: 'displayMethod' },
+ { name: 'informationLabel' },
+ { name: 'informationText' },
+ { name: 'informationUrl' },
+ { name: 'payCode' }
+ ] },
+ { name: 'assignmentId', type: 'object', properties: [
+ { name: 'id' }
+ ] },
+ { name: 'banks', type: 'array', of: 'object', properties: [
+ { name: 'bankId', type: 'integer' },
+ { name: 'label' },
+ { name: 'maxWarningThreshold', type: 'number' },
+ { name: 'minWarningThreshold', type: 'number' },
+ { name: 'transactions', type: 'array', of: 'object', properties: [
+ { name: 'amount', type: 'number' },
+ { name: 'newBalance', type: 'number' },
+ { name: 'sourceDescription' },
+ { name: 'type' },
+ { name: 'workDate', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' }
+ ] }
+ ] },
+ { name: 'unitsDescription' },
+ { name: 'unitsFormatPattern' }
+ ] },
+ { name: 'bankUsages', type: 'array', of: 'object', properties: [
+ { name: 'bankId', type: 'integer' },
+ { name: 'amount', type: 'number' }
+ ] },
+ { name: 'caseId', type: 'object', propeties: [
+ { name: 'id' }
+ ] },
+ { name: 'details', type: 'array', of: 'object', properties: [
+ { name: 'hours' },
+ { name: 'inTime', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' },
+ { name: 'hours', type: 'integer' },
+ { name: 'minutes', type: 'integer' },
+ { name: 'seconds', type: 'integer' }
+ ] },
+ { name: 'outTime', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' },
+ { name: 'hours', type: 'integer' },
+ { name: 'minutes', type: 'integer' },
+ { name: 'seconds', type: 'integer' }
+ ] },
+ { name: 'payCode' },
+ { name: 'workDate', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' }
+ ] }
+ ] },
+ { name: 'exceptions', type: 'array', of: 'object', properties: [
+ { name: 'message' },
+ { name: 'severity' },
+ { name: 'workDate', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' }
+ ] }
+ ] },
+ { name: 'historyEvents', type: 'array', of: 'object', properties: [
+ { name: 'comments' },
+ { name: 'status' },
+ { name: 'userName' },
+ { name: 'workDate', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' }
+ ] }
+ ] },
+ { name: 'permissions', type: 'object', properties: [
+ { name: 'canApprove', type: 'boolean' },
+ { name: 'canCancel', type: 'boolean' },
+ { name: 'canReject', type: 'boolean' },
+ { name: 'canSubmit', type: 'boolean' }
+ ] },
+ { name: 'showExceptionsAndBanks', type: 'boolean' },
+ { name: 'status' }
+ ] },
+ { name: 'statusResponse', type: 'object', propeties: [
+ { name: 'ERROR_MESSAGE' },
+ { name: 'STATUS' }
+ ] },
+ { name: 'timeOffRequestId', type: 'object', properties: [
+ { name: 'id' }
+ ] }
+ ] }
+ ]
+ end
+ },
+ time_off_request_details: {
+ fields: lambda do |_connection, _config_fields|
+ [
+ { name: 'detailedErrorMessage' },
+ { name: 'operationSuccessful' },
+ { name: 'resultCode' },
+ { name: 'resultDescription' },
+ { name: 'result', type: 'object', properties: [
+ { name: 'assignmentInfo', type: 'object', properties: [
+ { name: 'assignmentId', type: 'object', properties: [
+ { name: 'id' }
+ ] },
+ { name: 'assignmentDescription' }
+ ] },
+ { name: 'bankBalances', type: 'array', of: 'object', properties: [
+ { name: 'balance', type: 'number' },
+ { name: 'bankName' }
+ ] },
+ { name: 'comments' },
+ { name: 'employeeDisplayInfo', type: 'object', properties: [
+ { name: 'displayEmployee' },
+ { name: 'employeeId', type: 'object', properties: [
+ { name: 'id' }
+ ] },
+ { name: 'firstName' },
+ { name: 'lastName' }
+ ] },
+ { name: 'requestDateTime', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' },
+ { name: 'hours', type: 'integer' },
+ { name: 'minutes', type: 'integer' },
+ { name: 'seconds', type: 'integer' }
+ ] },
+ { name: 'timeOffHours', type: 'array', of: 'object', properties: [
+ { name: 'endDateTime', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' },
+ { name: 'hours', type: 'integer' },
+ { name: 'minutes', type: 'integer' },
+ { name: 'seconds', type: 'integer' }
+ ] },
+ { name: 'hours', type: 'number' },
+ { name: 'payCode' },
+ { name: 'startDateTime', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' },
+ { name: 'hours', type: 'integer' },
+ { name: 'minutes', type: 'integer' },
+ { name: 'seconds', type: 'integer' }
+ ] },
+ { name: 'workDate', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' }
+ ] }
+ ] },
+ { name: 'timeOffRequestId', type: 'object', properties: [
+ { name: 'id' }
+ ] },
+ { name: 'torEndDate', label: 'Time of request end date',
+ type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' }
+ ] },
+ { name: 'torStartDate', label: 'Time of request start date',
+ type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' }
+ ] },
+ { name: 'torExceptions', type: 'array', of: 'object', properties: [
+ { name: 'dateTime', type: 'object', properties: [
+ { name: 'day', type: 'integer' },
+ { name: 'month', type: 'integer' },
+ { name: 'year', type: 'integer' },
+ { name: 'hours', type: 'integer' },
+ { name: 'minutes', type: 'integer' },
+ { name: 'seconds', type: 'integer' }
+ ] },
+ { name: 'message' },
+ { name: 'severity', type: 'object', properties: [
+ { name: 'exception_severity' }
+ ] },
+ { name: 'torStatus', label: 'Time off request status', type: 'object', properties: [
+ { name: 'time_off_request_status' }
+ ] }
+ ] }
+ ] }
+ ]
+ end
+ },
+ multipart_form_parts: {
+ fields: lambda do |_|
+ [
+ { name: 'multipart_form_boundary' },
+ {
+ name: 'multipart_form_parts', type: 'array', of: 'object', properties: [
+ {
+ name: 'content_headers', type: 'array', of: 'object', properties: [
+ { name: 'key' },
+ { name: 'value' }
+ ]
+ },
+ { name: 'content_body' }
+ ]
+ },
+ { name: 'code' },
+ { name: 'headers', type: 'object' },
+ { name: 'body' }
+ ]
+ end
+ }
+ },
+ actions: {
+ submit_timeoff_request: {
+ title: 'Submits a time off request',
+ input_fields: lambda do |object_definitions|
+ object_definitions['submit_time_off_request']
+ end,
+ execute: lambda do |connection, input|
+ nonce = "#{now.to_i}workato"
+ created_time = now.to_time.strftime('%Y-%m-%dT%H:%M:%SZ')
+ password_digest = (nonce + created_time + connection['password']).sha1.encode_base64
+
+ post('/workforce/services/E2G_submitTimeOffRequest').
+ payload("soapenv:Header": [{
+ 'wsse:Security': [{
+ '@xmlns:wsse': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ '@soapenv:mustUnderstand': '1',
+ 'wsse:UsernameToken': [{
+ '@wsu:Id': 'UsernameToken-CBF92886ABADBFD1E715712314369112',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ 'wsse:Username': [{
+ "content!": connection['user_name']
+ }],
+ 'wsse:Password': [{
+ '@Type':
+ 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest',
+ "content!": password_digest
+ }],
+ 'wsse:Nonce': [{
+ '@EncodingType': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary',
+ "content!": nonce.base64
+ }],
+ 'wsu:Created': [{
+ "content!": created_time
+ }]
+ }]
+ }]
+ }],
+ "soapenv:Body": [{
+ 'xsd:E2G_submitTimeOffRequest': [{
+ 'xsd:submitRequest': [{
+ 'xsd1:detailRequest':
+ [call('build_request_fields_xml', input)],
+ 'xsd1:requestDateRange': [{
+ 'xsd1:endDate': [{
+ 'xsd2:day': [{
+ "content!": input&.
+ dig('requestDateRange', 'endDate')&.
+ strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": input&.
+ dig('requestDateRange', 'endDate')&.
+ strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": input&.
+ dig('requestDateRange', 'endDate')&.
+ strftime('%Y')
+ }]
+ }],
+ 'xsd1:startDate': [{
+ 'xsd2:day': [{
+ "content!": input&.
+ dig('requestDateRange', 'startDate')&.
+ strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": input&.
+ dig('requestDateRange', 'startDate')&.
+ strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": input&.
+ dig('requestDateRange', 'startDate')&.
+ strftime('%Y')
+ }]
+ }]
+ }]
+ }]
+ }]
+ }]).
+ headers('Content-Type': 'text/xml;charset=UTF-8').
+ format_xml('soapenv:Envelope',
+ '@xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ '@xmlns:xsd1' => 'http://ws.apache.org/axis2/xsd',
+ '@xmlns:xsd2' => 'http://data.service.webservices.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts:
+ call(:extract_multipart_parts,
+ { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ },
+ approve_time_off_request: {
+ title: 'Approves the time-off request',
+ help: 'User invoking this action must have one of the following ' \
+ 'system features assigned in order to successfully perform the ' \
+ 'operation
E2G_TIMEOFF_REQUEST_APPROVAL 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ '@xmlns:xsd1' => 'http://ws.apache.org/axis2/xsd',
+ '@xmlns:xsd2' => 'http://data.service.webservices.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts: call(:extract_multipart_parts,
+ { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ },
+ reject_timeoff_request: {
+ title: 'Rejects the time-off request',
+ help: 'User invoking this action must have one of the following ' \
+ 'system features assigned in order to successfully perform the ' \
+ 'operation
E2G_TIMEOFF_REQUEST_APPROVAL 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ '@xmlns:xsd1' => 'http://ws.apache.org/axis2/xsd',
+ '@xmlns:xsd2' => 'http://data.service.webservices.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts: call(:extract_multipart_parts,
+ { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ },
+ change_time_off_request_status: {
+ title: 'Changes a time-off request status',
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'comments', optional: true, sticky: true },
+ {
+ name: 'newStatus',
+ label: 'New status',
+ control_type: 'select',
+ pick_list: [
+ %w[Approved APPROVED],
+ %w[Rejected REJECTED],
+ %w[Cancelled CANCELLED]
+ ],
+ optional: false,
+ hint: 'The status is changed only if the user is allowed to change the time off request status.',
+ toggle_hint: 'Select from list',
+ toggle_field: {
+ name: 'newStatus',
+ label: 'New status',
+ type: 'string',
+ control_type: 'text',
+ optional: false,
+ toggle_hint: 'Use custom value',
+ hint: 'Valid values are: REJECTED, APPROVED or CANCELLED.'
+ }
+ },
+ { name: 'requestId', label: 'Time-off request ID', optional: false }
+ ]
+ end,
+ execute: lambda do |connection, input|
+ nonce = "#{now.to_i}workto"
+ created_time = now.to_time.strftime('%Y-%m-%dT%H:%M:%SZ')
+ password_digest = (nonce + created_time + connection['password']).sha1.encode_base64
+
+ post('/workforce/services/E2G_changeTimeOffRequestStatus').
+ payload("soapenv:Header": [{
+ 'wsse:Security': [{
+ '@xmlns:wsse': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ '@soapenv:mustUnderstand': '1',
+ 'wsse:UsernameToken': [{
+ '@wsu:Id': 'UsernameToken-CBF92886ABADBFD1E715712314369112',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ 'wsse:Username': [{
+ "content!": connection['user_name']
+ }],
+ 'wsse:Password': [{
+ '@Type': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest',
+ "content!": password_digest
+ }],
+ 'wsse:Nonce': [{
+ '@EncodingType': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary',
+ "content!": nonce.base64
+ }],
+ 'wsu:Created': [{
+ "content!": created_time
+ }]
+ }]
+ }]
+ }],
+ "soapenv:Body": [{
+ 'xsd:E2G_changeTimeOffRequestStatus': [{
+ 'xsd:statusChangeRequest': [{
+ 'xsd1:comments': [{
+ "content!": input['comments']
+ }],
+ 'xsd1:newStatus': [{
+ 'xsd2:time_off_request_status': [{
+ "content!": input['newStatus']
+ }]
+ }],
+ 'xsd1:requestId': [{
+ 'xsd2:id': [{
+ "content!": input['requestId']
+ }]
+ }]
+ }]
+ }]
+ }]).
+ headers('Content-Type': 'text/xml;charset=UTF-8').
+ format_xml('soapenv:Envelope',
+ '@xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ '@xmlns:xsd1' => 'http://ws.apache.org/axis2/xsd',
+ '@xmlns:xsd2' => 'http://data.service.webservices.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts: call(:extract_multipart_parts,
+ { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ },
+ get_timeoff_request_details: {
+ title: 'Gets details for a time off request',
+ hint: 'User invoking this service must have one of the following system' \
+ ' features assigned in order to successfully perform the operation.
' \
+ 'E2G_TIMEOFF_REQUEST_APPROVAL',
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'timeOffRequestId', type: 'integer', optional: false },
+ { name: 'userId', hint: 'User ID to be used for Impersonation.', label: 'User ID' }
+ ]
+ end,
+ execute: lambda do |connection, input|
+ nonce = "#{now.to_i}workto"
+ created_time = now.to_time.strftime('%Y-%m-%dT%H:%M:%SZ')
+ password_digest = (nonce + created_time + connection['password']).sha1.encode_base64
+
+ post('/workforce/services/E2G_getTimeOffRequestDetails').
+ payload("soapenv:Header": [{
+ 'wsse:Security': [{
+ '@xmlns:wsse': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ '@soapenv:mustUnderstand': '1',
+ 'wsse:UsernameToken': [{
+ '@wsu:Id': 'UsernameToken-CBF92886ABADBFD1E715712314369112',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ 'wsse:Username': [{
+ "content!": connection['user_name']
+ }],
+ 'wsse:Password': [{
+ '@Type': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest',
+ "content!": password_digest
+ }],
+ 'wsse:Nonce': [{
+ '@EncodingType': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary',
+ "content!": nonce.base64
+ }],
+ 'wsu:Created': [{
+ "content!": created_time
+ }]
+ }]
+ }],
+ 'wfswse:Impersonate': [{
+ '@xmlns:wfswse': 'http://services.workforcesoftware.com/xsd',
+ 'wfswse:UserId': [{
+ "content!": input['userId']
+ }]
+ }]
+ }],
+ "soapenv:Body": [{
+ 'xsd:E2G_getTimeOffRequestDetails': [{
+ 'xsd:timeOffRequestId': [{
+ 'xsd1:id': [{ "content!": input['timeOffRequestId'] }]
+ }]
+ }]
+ }]).
+ headers('Content-Type': 'text/xml;charset=UTF-8').
+ format_xml('soapenv:Envelope',
+ '@xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ '@xmlns:xsd1' => 'http://data.service.webservices.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts:
+ call(:extract_multipart_parts, { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ },
+ validate_token: {
+
+ execute: lambda do |connection|
+ nonce = now.to_i.to_s + 'workto'
+ created_time = now.to_time.strftime('%Y-%m-%dT%H:%M:%SZ')
+ password_digest = (nonce + created_time + connection['password']).sha1.encode_base64
+
+ post('/workforce/services/E2G_getEmployeeList/').
+ payload("soapenv:Header": [{
+ 'wsse:Security': [{
+ '@xmlns:wsse': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ '@soapenv:mustUnderstand': '1',
+ 'wsse:UsernameToken': [{
+ '@wsu:Id': 'UsernameToken-CBF92886ABADBFD1E715712314369112',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ 'wsse:Username': [{
+ "content!": connection['user_name']
+ }],
+ 'wsse:Password': [{
+ '@Type': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest',
+ "content!": password_digest
+ }],
+ 'wsse:Nonce': [{
+ '@EncodingType': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary',
+ "content!": nonce.base64
+ }],
+ 'wsu:Created': [{
+ "content!": created_time
+ }]
+ }]
+ }]
+ }],
+ "soapenv:Body": [{
+ 'xsd:E2G_getEmployeeList': [{
+ "content!": nil
+ }]
+ }]).
+ headers('Content-Type': 'text/xml;charset=UTF-8',
+ 'Accept': 'gzip,deflate').
+ format_xml('soapenv:Envelope',
+ '@xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts: call(:extract_multipart_parts, { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ },
+ get_version: {
+ execute: lambda do |connection|
+ nonce = now.to_i.to_s + 'workto'
+ created_time = now.to_time.strftime('%Y-%m-%dT%H:%M:%SZ')
+ password_digest = (nonce + created_time + connection['password']).sha1.encode_base64
+
+ post('https://central-dev.workforcehosting.eu/workforce/services/E2G_getVersion/').
+ payload("soapenv:Header": [{
+ 'wsse:Security': [{
+ '@xmlns:wsse': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ '@soapenv:mustUnderstand': '1',
+ 'wsse:UsernameToken': [{
+ '@wsu:Id': 'UsernameToken-CBF92886ABADBFD1E715712314369112',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ 'wsse:Username': [{
+ "content!": connection['user_name']
+ }],
+ 'wsse:Password': [{
+ '@Type': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest',
+ "content!": password_digest
+ }],
+ 'wsse:Nonce': [{
+ '@EncodingType': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary',
+ "content!": nonce.base64
+ }],
+ 'wsu:Created': [{
+ "content!": created_time
+ }]
+ }]
+ }]
+ }],
+ "soapenv:Body": [{
+ 'xsd:getVersion': [{}]
+ }]).
+ headers('Content-Type': 'text/xml;charset=UTF-8',
+ 'Accept': 'gzip,deflate',
+ 'SOAPAction': 'urn:E2G_getVersion').
+ format_xml('soapenv:Envelope',
+ '@xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts: call(:extract_multipart_parts, { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end
+ },
+ get_leave_balances: {
+ title: 'Get leave balance by employee',
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'employeeMatchValue', label: 'Employee ID', optional: false },
+ { name: 'startDate', type: 'date', label: 'Start date', optional: false },
+ { name: 'endDate', type: 'date', label: 'End date', optional: false }
+ ]
+ end,
+ execute: lambda do |connection, input|
+ nonce = "#{now.to_i}workto"
+ created_time = now.to_time.strftime('%Y-%m-%dT%H:%M:%SZ')
+ password_digest = (nonce + created_time + connection['password']).sha1.encode_base64
+ post('/workforce/services/E2G_getBankBalances').
+ payload("soapenv:Header": [{
+ 'wsse:Security': [{
+ '@xmlns:wsse': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ '@soapenv:mustUnderstand': '1',
+ 'wsse:UsernameToken': [{
+ '@wsu:Id': 'UsernameToken-CBF92886ABADBFD1E715712314369112',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ 'wsse:Username': [{
+ "content!": connection['user_name']
+ }],
+ 'wsse:Password': [{
+ '@Type': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest',
+ "content!": password_digest
+ }],
+ 'wsse:Nonce': [{
+ '@EncodingType': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary',
+ "content!": nonce.base64
+ }],
+ 'wsu:Created': [{
+ "content!": created_time
+ }]
+ }]
+ }]
+ }],
+ "soapenv:Body": [{
+ 'xsd:E2G_getBankBalances': [{
+ 'xsd:payload': [{
+ 'xsd1:dateRange': [{
+ 'xsd1:endDate': [{
+ 'xsd2:day': [{
+ "content!": input['endDate']&.strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": input['endDate']&.strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": input['endDate']&.strftime('%Y')
+ }]
+ }],
+ 'xsd1:startDate': [{
+ 'xsd2:day': [{
+ "content!": input['startDate']&.strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": input['startDate']&.strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": input['startDate']&.strftime('%Y')
+ }]
+ }]
+ }],
+ 'xsd1:employeeMatchValue': [{
+ "content!": input['employeeMatchValue']
+ }]
+ }]
+ }]
+ }]).
+ headers('Content-Type': 'text/xml;charset=UTF-8').
+ format_xml('soapenv:Envelope',
+ '@xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ '@xmlns:xsd1' => 'http://ws.apache.org/axis2/xsd',
+ '@xmlns:xsd2' => 'http://data.service.webservices.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts:
+ call(:extract_multipart_parts, { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ },
+ get_periods: {
+ title: 'Get periods by employee',
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'asgnmtInfo', label: 'Assignment info', type: 'object',
+ optional: false, sticky: true,
+ properties: [
+ { name: 'assignmentDescription' },
+ { name: 'assignmentId' }
+ ] },
+ { name: 'numberOfPriorPeriods', type: 'number', sticky: true,
+ hint: 'Number of prior periods needed to be fetched along with' \
+ ' the period for which requestDate belongs.' },
+ { name: 'requestDate', type: 'date', optional: false,
+ hint: 'The date for which the period must be fetched.' }
+ ]
+ end,
+ execute: lambda do |connection, input|
+ nonce = "#{now.to_i}workto"
+ created_time = now.to_time.strftime('%Y-%m-%dT%H:%M:%SZ')
+ password_digest = (nonce + created_time + connection['password']).sha1.encode_base64
+ post('/workforce/services/E2G_getPeriods').
+ payload("soapenv:Header": [{
+ 'wsse:Security': [{
+ '@xmlns:wsse': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ '@soapenv:mustUnderstand': '1',
+ 'wsse:UsernameToken': [{
+ '@wsu:Id': 'UsernameToken-CBF92886ABADBFD1E715712314369112',
+ '@xmlns:wsu': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd',
+ 'wsse:Username': [{
+ "content!": connection['user_name']
+ }],
+ 'wsse:Password': [{
+ '@Type': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest',
+ "content!": password_digest
+ }],
+ 'wsse:Nonce': [{
+ '@EncodingType': 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary',
+ "content!": nonce.base64
+ }],
+ 'wsu:Created': [{
+ "content!": created_time
+ }]
+ }]
+ }]
+ }],
+ "soapenv:Body": [{
+ 'xsd:E2G_getPeriods': [{
+ 'xsd:request': [{
+ 'xsd1:asgnmtInfo': [{
+ 'xsd1:assignmentDescription': [{
+ "content!": input&.dig('asgnmtInfo', 'assignmentDescription')
+ }],
+ 'xsd1:assignmentId': [{
+ 'xsd2:id': [{
+ "content!": input&.dig('asgnmtInfo', 'assignmentId')
+ }]
+ }]
+ }],
+ 'xsd1:requestDate': [{
+ 'xsd2:day': [{
+ "content!": input['requestDate']&.strftime('%d')
+ }],
+ 'xsd2:month': [{
+ "content!": input['requestDate']&.strftime('%m')
+ }],
+ 'xsd2:year': [{
+ "content!": input['requestDate']&.strftime('%Y')
+ }]
+ }],
+ 'xsd1:numberOfPriorPeriods': [{
+ "content!": input['numberOfPriorPeriods']
+ }]
+ }]
+ }]
+ }]).
+ headers('Content-Type': 'text/xml;charset=UTF-8').
+ format_xml('soapenv:Envelope',
+ '@xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ '@xmlns:xsd' => 'http://services.workforcesoftware.com/xsd',
+ '@xmlns:xsd1' => 'http://ws.apache.org/axis2/xsd',
+ '@xmlns:xsd2' => 'http://data.service.webservices.workforcesoftware.com/xsd',
+ strip_response_namespaces: true).
+ response_format_raw.after_response do |code, body, headers|
+ if code.to_i != 200
+ error("#{code}:#{body}")
+ else
+ multipart_form_boundary = "--#{call(:extract_multipart_boundary, headers)}"
+ {
+ multipart_form_boundary: multipart_form_boundary,
+ multipart_form_parts:
+ call(:extract_multipart_parts, { multipart_form_boundary: multipart_form_boundary, body: body }),
+ code: code,
+ headers: headers,
+ body: body
+ }
+ end
+ end
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['multipart_form_parts']
+ end
+ }
+ }
+}