rhoconnect-adapters 1.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/CHANGELOG +4 -0
- data/Gemfile +18 -0
- data/README.md +239 -0
- data/Rakefile +31 -0
- data/bin/rhoconnect-adapters +35 -0
- data/generators/crm/templates/application/application.rb +34 -0
- data/generators/crm/templates/source/source_adapter.rb +10 -0
- data/generators/crm/templates/source/source_spec.rb +25 -0
- data/generators/crm/templates/spec/spec_helper.rb +64 -0
- data/generators/crm/vendor/ms_dynamics/adapter.rb +301 -0
- data/generators/crm/vendor/ms_dynamics/application.rb +56 -0
- data/generators/crm/vendor/ms_dynamics/lib/crm_metadata_service.rb +43 -0
- data/generators/crm/vendor/ms_dynamics/lib/crm_service.rb +141 -0
- data/generators/crm/vendor/ms_dynamics/lib/discovery_service.rb +51 -0
- data/generators/crm/vendor/ms_dynamics/lib/wlid_service.rb +159 -0
- data/generators/crm/vendor/ms_dynamics/ms_dynamics.rb +45 -0
- data/generators/crm/vendor/ms_dynamics/settings/Account.yml +46 -0
- data/generators/crm/vendor/ms_dynamics/settings/Contact.yml +40 -0
- data/generators/crm/vendor/ms_dynamics/settings/GenericObject.yml +18 -0
- data/generators/crm/vendor/ms_dynamics/settings/Lead.yml +53 -0
- data/generators/crm/vendor/ms_dynamics/settings/Opportunity.yml +41 -0
- data/generators/crm/vendor/ms_dynamics/settings/settings.yml +9 -0
- data/generators/crm/vendor/ms_dynamics/spec/application_spec.rb +23 -0
- data/generators/crm/vendor/ms_dynamics/spec/sources/account_spec.rb +49 -0
- data/generators/crm/vendor/ms_dynamics/spec/sources/contact_spec.rb +49 -0
- data/generators/crm/vendor/ms_dynamics/spec/sources/lead_spec.rb +49 -0
- data/generators/crm/vendor/ms_dynamics/spec/sources/opportunity_spec.rb +62 -0
- data/generators/crm/vendor/ms_dynamics/spec/spec_helper.rb +78 -0
- data/generators/crm/vendor/ms_dynamics/spec_data/Account.yml +6 -0
- data/generators/crm/vendor/ms_dynamics/spec_data/Contact.yml +7 -0
- data/generators/crm/vendor/ms_dynamics/spec_data/GenericObject.yml +3 -0
- data/generators/crm/vendor/ms_dynamics/spec_data/Lead.yml +12 -0
- data/generators/crm/vendor/ms_dynamics/spec_data/Opportunity.yml +6 -0
- data/generators/crm/vendor/ms_dynamics/templates.rb +57 -0
- data/generators/crm/vendor/oracle_on_demand/adapter.rb +421 -0
- data/generators/crm/vendor/oracle_on_demand/application.rb +64 -0
- data/generators/crm/vendor/oracle_on_demand/settings/Account.yml +91 -0
- data/generators/crm/vendor/oracle_on_demand/settings/Contact.yml +54 -0
- data/generators/crm/vendor/oracle_on_demand/settings/GenericObject.yml +21 -0
- data/generators/crm/vendor/oracle_on_demand/settings/Lead.yml +72 -0
- data/generators/crm/vendor/oracle_on_demand/settings/Opportunity.yml +69 -0
- data/generators/crm/vendor/oracle_on_demand/settings/settings.yml +8 -0
- data/generators/crm/vendor/oracle_on_demand/spec/application_spec.rb +14 -0
- data/generators/crm/vendor/oracle_on_demand/spec/sources/account_spec.rb +50 -0
- data/generators/crm/vendor/oracle_on_demand/spec/sources/contact_spec.rb +50 -0
- data/generators/crm/vendor/oracle_on_demand/spec/sources/lead_spec.rb +51 -0
- data/generators/crm/vendor/oracle_on_demand/spec/sources/opportunity_spec.rb +51 -0
- data/generators/crm/vendor/oracle_on_demand/spec_data/Account.yml +8 -0
- data/generators/crm/vendor/oracle_on_demand/spec_data/Contact.yml +8 -0
- data/generators/crm/vendor/oracle_on_demand/spec_data/GenericObject.yml +4 -0
- data/generators/crm/vendor/oracle_on_demand/spec_data/Lead.yml +14 -0
- data/generators/crm/vendor/oracle_on_demand/spec_data/Opportunity.yml +6 -0
- data/generators/crm/vendor/oracle_on_demand/templates.rb +52 -0
- data/generators/crm/vendor/salesforce/adapter.rb +315 -0
- data/generators/crm/vendor/salesforce/application.rb +80 -0
- data/generators/crm/vendor/salesforce/settings/Account.yml +53 -0
- data/generators/crm/vendor/salesforce/settings/Contact.yml +61 -0
- data/generators/crm/vendor/salesforce/settings/GenericObject.yml +13 -0
- data/generators/crm/vendor/salesforce/settings/Lead.yml +73 -0
- data/generators/crm/vendor/salesforce/settings/Opportunity.yml +48 -0
- data/generators/crm/vendor/salesforce/settings/settings.yml +6 -0
- data/generators/crm/vendor/salesforce/spec/application_spec.rb +14 -0
- data/generators/crm/vendor/salesforce/spec/sources/account_spec.rb +50 -0
- data/generators/crm/vendor/salesforce/spec/sources/contact_spec.rb +50 -0
- data/generators/crm/vendor/salesforce/spec/sources/lead_spec.rb +51 -0
- data/generators/crm/vendor/salesforce/spec/sources/opportunity_spec.rb +51 -0
- data/generators/crm/vendor/salesforce/spec_data/Account.yml +14 -0
- data/generators/crm/vendor/salesforce/spec_data/Contact.yml +8 -0
- data/generators/crm/vendor/salesforce/spec_data/GenericObject.yml +3 -0
- data/generators/crm/vendor/salesforce/spec_data/Lead.yml +10 -0
- data/generators/crm/vendor/salesforce/spec_data/Opportunity.yml +10 -0
- data/generators/crm/vendor/salesforce/templates.rb +45 -0
- data/generators/crm/vendor/sugar/adapter.rb +291 -0
- data/generators/crm/vendor/sugar/application.rb +50 -0
- data/generators/crm/vendor/sugar/settings/Account.yml +49 -0
- data/generators/crm/vendor/sugar/settings/Contact.yml +62 -0
- data/generators/crm/vendor/sugar/settings/GenericObject.yml +12 -0
- data/generators/crm/vendor/sugar/settings/Lead.yml +76 -0
- data/generators/crm/vendor/sugar/settings/Opportunity.yml +49 -0
- data/generators/crm/vendor/sugar/settings/settings.yml +9 -0
- data/generators/crm/vendor/sugar/spec/application_spec.rb +25 -0
- data/generators/crm/vendor/sugar/spec/sources/account_spec.rb +53 -0
- data/generators/crm/vendor/sugar/spec/sources/contact_spec.rb +53 -0
- data/generators/crm/vendor/sugar/spec/sources/lead_spec.rb +54 -0
- data/generators/crm/vendor/sugar/spec/sources/opportunity_spec.rb +54 -0
- data/generators/crm/vendor/sugar/spec_data/Account.yml +13 -0
- data/generators/crm/vendor/sugar/spec_data/Contact.yml +8 -0
- data/generators/crm/vendor/sugar/spec_data/GenericObject.yml +3 -0
- data/generators/crm/vendor/sugar/spec_data/Lead.yml +16 -0
- data/generators/crm/vendor/sugar/spec_data/Opportunity.yml +10 -0
- data/generators/crm/vendor/sugar/sugar.rb +33 -0
- data/generators/crm/vendor/sugar/templates.rb +58 -0
- data/generators/rhoconnect-adapters.rb +217 -0
- data/lib/rhoconnect-adapters/crm/crm.rb +31 -0
- data/lib/rhoconnect-adapters/soap_service.rb +70 -0
- data/lib/rhoconnect-adapters/version.rb +3 -0
- data/lib/rhoconnect-adapters.rb +2 -0
- data/rhoconnect-adapters.gemspec +36 -0
- data/spec/apps/ms_dynamics_spec.rb +19 -0
- data/spec/apps/oracle_on_demand_spec.rb +20 -0
- data/spec/apps/salesforce_spec.rb +18 -0
- data/spec/apps/sugar_spec.rb +18 -0
- data/spec/generator/generator_spec.rb +113 -0
- data/spec/spec_helper.rb +57 -0
- metadata +288 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
module RhoconnectAdapters
|
|
2
|
+
module CRM
|
|
3
|
+
module MsDynamics
|
|
4
|
+
class WlidService < SoapService
|
|
5
|
+
def self.get_ticket(user_name,password)
|
|
6
|
+
# device client ID
|
|
7
|
+
client_id = UUIDTools::UUID.random_create
|
|
8
|
+
# random device name
|
|
9
|
+
device_name = rand(10000).to_s+'12345678901234567890'
|
|
10
|
+
# random device password
|
|
11
|
+
device_password = 'random-device-password'
|
|
12
|
+
# authentication policy
|
|
13
|
+
policy = "MBI_SSL"
|
|
14
|
+
# open information about CRM Online
|
|
15
|
+
partner = "crm.dynamics.com";
|
|
16
|
+
# Get authorization endpoint
|
|
17
|
+
authorization_endpoint = self._get_authorization_endpoint
|
|
18
|
+
# Do the following once per machine.
|
|
19
|
+
# Register each machine that you need to authenticate with.
|
|
20
|
+
self._register_machine(device_name,device_password,client_id)
|
|
21
|
+
# Get device token based for the registered machine
|
|
22
|
+
device_token = self._get_device_token(authorization_endpoint,device_name,device_password)
|
|
23
|
+
# Get WLID Ticket for the user
|
|
24
|
+
self._get_ticket(authorization_endpoint,user_name,password,partner,policy,client_id,device_token)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
class << self
|
|
29
|
+
def _get_authorization_endpoint
|
|
30
|
+
xml = RestClient.get("https://nexus.passport.com/federationmetadata/2006-12/FederationMetaData.xml")
|
|
31
|
+
federation_metadata = Nokogiri::XML(xml)
|
|
32
|
+
federation_metadata.xpath("//fed:FederationMetadata/fed:Federation/fed:TargetServiceEndpoint/wsa:Address").text.strip
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Registers a machine/device with the device registration Windows Live ID service.
|
|
36
|
+
# Device registration is required only once per computer or device.
|
|
37
|
+
# The result of this request will contain the PUID (Device ID) of the device registered
|
|
38
|
+
# and should be saved for later use.
|
|
39
|
+
# device_name - The random device name to use for this registration.
|
|
40
|
+
# device_password - The random device password to use for this registration.
|
|
41
|
+
# client_id - The app GUID, a unique id for the client/application.
|
|
42
|
+
def _register_machine(device_name,device_password,client_id)
|
|
43
|
+
device_registration_request =
|
|
44
|
+
"<DeviceAddRequest>
|
|
45
|
+
<ClientInfo name=\"#{client_id}\" version=\"1.0\"/>
|
|
46
|
+
<Authentication>
|
|
47
|
+
<Membername>11#{device_name}</Membername>
|
|
48
|
+
<Password>#{device_password}</Password>
|
|
49
|
+
</Authentication>
|
|
50
|
+
</DeviceAddRequest>"
|
|
51
|
+
windows_live_device_url = "https://login.live.com/ppsecure/DeviceAddCredential.srf"
|
|
52
|
+
doc = send_request(windows_live_device_url,device_registration_request,nil,"application/soap+xml; charset=UTF-8")
|
|
53
|
+
raise "Can't register machine with Wndows Live ID" if select_node(doc,'//DeviceAddResponse/@Success').to_s.strip != 'true'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Validate Windows Live ID response for any exception.
|
|
57
|
+
# doc - The Windows Live ID service response.
|
|
58
|
+
# source - An exception source.
|
|
59
|
+
# Raise runtime error is request is invalid
|
|
60
|
+
def _is_response_valid(doc,source)
|
|
61
|
+
if select_node(doc,'//s:Fault').size > 0
|
|
62
|
+
error = "Unknown error"
|
|
63
|
+
begin
|
|
64
|
+
reason = select_node_text(doc,'//s:Reason/s:Text')
|
|
65
|
+
details = select_node_text(doc,'//psf:text')
|
|
66
|
+
code = select_node_text(doc,'//psf:code')
|
|
67
|
+
error = "#{reason} (#{code}): #{details}"
|
|
68
|
+
rescue; end
|
|
69
|
+
begin
|
|
70
|
+
raise "#{self.name} error w/ #{source}: #{error}"
|
|
71
|
+
rescue Exception => ex
|
|
72
|
+
warn "#{self.name} error: " + ex.inspect.strip
|
|
73
|
+
ex.backtrace.each { |line| warn 'from ' + line }
|
|
74
|
+
raise ex
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def _compose_header(user_token_id,user,password,client_id=nil,device_token=nil)
|
|
80
|
+
app_info = client_id ?
|
|
81
|
+
"<ps:AuthInfo Id=\"PPAuthInfo\" xmlns:ps=\"http://schemas.microsoft.com/LiveID/SoapServices/v1\">
|
|
82
|
+
<ps:HostingApp>#{client_id}</ps:HostingApp>
|
|
83
|
+
</ps:AuthInfo>" : ""
|
|
84
|
+
binary_security_token = device_token ?
|
|
85
|
+
"<wsse:BinarySecurityToken ValueType=\"urn:liveid:device\">
|
|
86
|
+
#{device_token}
|
|
87
|
+
</wsse:BinarySecurityToken>" : ""
|
|
88
|
+
header = "
|
|
89
|
+
<wsa:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
|
|
90
|
+
<wsa:To s:mustUnderstand=\"1\">http://Passport.NET/tb</wsa:To>
|
|
91
|
+
#{app_info}
|
|
92
|
+
<wsse:Security>
|
|
93
|
+
<wsse:UsernameToken wsu:Id=\"#{user_token_id}\">
|
|
94
|
+
<wsse:Username>#{user}</wsse:Username>
|
|
95
|
+
<wsse:Password>#{password}</wsse:Password>
|
|
96
|
+
</wsse:UsernameToken>
|
|
97
|
+
#{binary_security_token}
|
|
98
|
+
</wsse:Security>"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def _compose_body(address,policy=nil)
|
|
102
|
+
policy_reference = policy ? "<wsp:PolicyReference URI=\"#{policy}\"/>" : ""
|
|
103
|
+
body = "
|
|
104
|
+
<wst:RequestSecurityToken Id=\"RST0\">
|
|
105
|
+
<wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
|
|
106
|
+
<wsp:AppliesTo>
|
|
107
|
+
<wsa:EndpointReference>
|
|
108
|
+
<wsa:Address>#{address}</wsa:Address>
|
|
109
|
+
</wsa:EndpointReference>
|
|
110
|
+
</wsp:AppliesTo>
|
|
111
|
+
#{policy_reference}
|
|
112
|
+
</wst:RequestSecurityToken>"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Get a device authorization token from the Windows Live ID service.
|
|
116
|
+
# authorization_endpoint - Authorization endpoint
|
|
117
|
+
# device_name - The random device name used for this registration.
|
|
118
|
+
# device_password - The random device password used for this registration.
|
|
119
|
+
# Returns - The device token to use when retrieving a user token
|
|
120
|
+
def _get_device_token(authorization_endpoint,device_name,device_password)
|
|
121
|
+
header = _compose_header('devicesoftware',"11#{device_name}",device_password)
|
|
122
|
+
body = _compose_body('http://Passport.NET/tb')
|
|
123
|
+
message = compose_message(header,body)
|
|
124
|
+
# call authorization endpoint
|
|
125
|
+
doc = send_request(authorization_endpoint,message,nil,"application/soap+xml; charset=UTF-8")
|
|
126
|
+
# validate response and raise if invalid
|
|
127
|
+
_is_response_valid(doc,"IssueDeviceToken")
|
|
128
|
+
# get device token
|
|
129
|
+
select_node(doc,'//wst:RequestedSecurityToken/*')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Gets a Windows Live ID RequestSecurityTokenResponse ticket for a specified user.
|
|
133
|
+
# authorization_endpoint - Authorization endpoint
|
|
134
|
+
# user_name - The Windows Live ID email address for the user.
|
|
135
|
+
# password - The Windows Live ID password for the user.
|
|
136
|
+
# partner - sitename, i.e. crmapp.www.local-titan.com
|
|
137
|
+
# policy - auth policy, i.e. MBI_SSL
|
|
138
|
+
# client_id - The unique id of the client/application
|
|
139
|
+
# device_token - The device token xml
|
|
140
|
+
# Returns - A string that contains the Windows Live ID ticket for
|
|
141
|
+
# the supplied paramters and ticket expiration date/time
|
|
142
|
+
def _get_ticket(authorization_endpoint,user_name,password,partner,policy,client_id,device_token)
|
|
143
|
+
header = _compose_header('user',user_name,password,client_id,device_token)
|
|
144
|
+
body = _compose_body(partner,policy)
|
|
145
|
+
message = compose_message(header,body)
|
|
146
|
+
# call authorization endpoint
|
|
147
|
+
doc = send_request(authorization_endpoint,message,nil,"application/soap+xml; charset=UTF-8")
|
|
148
|
+
# validate response and raise if invalid
|
|
149
|
+
_is_response_valid(doc,"IssueTicket")
|
|
150
|
+
# get ticket
|
|
151
|
+
expires = DateTime.parse(select_node_text(doc,'//wst:Lifetime/wsu:Expires'))
|
|
152
|
+
ticket = select_node_text(doc,'//wsse:BinarySecurityToken')
|
|
153
|
+
[CGI::escape(ticket),expires]
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'uuidtools'
|
|
3
|
+
require 'rest-client'
|
|
4
|
+
require 'nokogiri'
|
|
5
|
+
require 'date'
|
|
6
|
+
|
|
7
|
+
require 'rhoconnect-adapters/soap_service'
|
|
8
|
+
require 'vendor/ms_dynamics/lib/wlid_service'
|
|
9
|
+
require 'vendor/ms_dynamics/lib/discovery_service'
|
|
10
|
+
require 'vendor/ms_dynamics/lib/crm_service'
|
|
11
|
+
require 'vendor/ms_dynamics/lib/crm_metadata_service'
|
|
12
|
+
|
|
13
|
+
module RhoconnectAdapters
|
|
14
|
+
module CRM
|
|
15
|
+
module MsDynamics
|
|
16
|
+
RhoconnectAdapters::SoapService.node_namespaces.merge!({'cds' => 'http://schemas.microsoft.com/crm/2007/CrmDiscoveryService',
|
|
17
|
+
'wst' => 'http://schemas.xmlsoap.org/ws/2005/02/trust',
|
|
18
|
+
's' => 'http://www.w3.org/2003/05/soap-envelope',
|
|
19
|
+
'psf' => 'http://schemas.microsoft.com/Passport/SoapServices/SOAPFault',
|
|
20
|
+
'cws6' => 'http://schemas.microsoft.com/crm/2006/WebServices',
|
|
21
|
+
'cws7' => 'http://schemas.microsoft.com/crm/2007/WebServices'});
|
|
22
|
+
RhoconnectAdapters::SoapService.envelope_namespaces += <<-DESC
|
|
23
|
+
xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"
|
|
24
|
+
xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\"
|
|
25
|
+
xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"
|
|
26
|
+
xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\"
|
|
27
|
+
DESC
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
def save_auth_info(username,auth_info)
|
|
31
|
+
Store.put_data(auth_info_key(username),"#{username}"=>auth_info)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load_auth_info(username)
|
|
35
|
+
Store.get_data(auth_info_key(username))[username]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
def auth_info_key(username)
|
|
40
|
+
"#{username}-msdynamics-auth-info"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Query_Fields:
|
|
2
|
+
# This is just a sample list of fields
|
|
3
|
+
# that are used in Query
|
|
4
|
+
accountid:
|
|
5
|
+
Label: Id
|
|
6
|
+
Type: id
|
|
7
|
+
name:
|
|
8
|
+
Label: Name
|
|
9
|
+
Type: textinput
|
|
10
|
+
accountnumber:
|
|
11
|
+
Label: Account Number
|
|
12
|
+
Type: textinput
|
|
13
|
+
telephone1:
|
|
14
|
+
Label: Main Phone
|
|
15
|
+
Type: textinput
|
|
16
|
+
emailaddress1:
|
|
17
|
+
Label: E-mail
|
|
18
|
+
Type: textinput
|
|
19
|
+
websiteurl:
|
|
20
|
+
Label: Web Site
|
|
21
|
+
Type: textinput
|
|
22
|
+
accountcategorycode:
|
|
23
|
+
Label: Category
|
|
24
|
+
Type: Picklist
|
|
25
|
+
industrycode:
|
|
26
|
+
Label: Industry
|
|
27
|
+
Type: Picklist
|
|
28
|
+
numberofemployees:
|
|
29
|
+
Label: Number Of Employees
|
|
30
|
+
Type: textinput
|
|
31
|
+
description:
|
|
32
|
+
Label: Description
|
|
33
|
+
Type: textarea
|
|
34
|
+
|
|
35
|
+
AttributeTypePicklists:
|
|
36
|
+
# these Picklists define values
|
|
37
|
+
# for artificially constructed fields
|
|
38
|
+
# that are really represent some other field's type
|
|
39
|
+
|
|
40
|
+
ObjectFields:
|
|
41
|
+
# these are reference fields to the other objects
|
|
42
|
+
|
|
43
|
+
TitleFields:
|
|
44
|
+
# these fields are concatenated to show the record
|
|
45
|
+
# in the Index form
|
|
46
|
+
- name
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Query_Fields:
|
|
2
|
+
# This is just a sample list of fields
|
|
3
|
+
# that are used in QueryPage
|
|
4
|
+
contactid:
|
|
5
|
+
Label: Id
|
|
6
|
+
Type: id
|
|
7
|
+
firstname:
|
|
8
|
+
Label: First Name
|
|
9
|
+
Type: textinput
|
|
10
|
+
lastname:
|
|
11
|
+
Label: Last Name
|
|
12
|
+
Type: textinput
|
|
13
|
+
jobtitle:
|
|
14
|
+
Label: Job Title
|
|
15
|
+
Type: textinput
|
|
16
|
+
emailaddress1:
|
|
17
|
+
Label: E-mail
|
|
18
|
+
Type: textinput
|
|
19
|
+
telephone1:
|
|
20
|
+
Label: Main Phone
|
|
21
|
+
Type: textinput
|
|
22
|
+
mobilephone:
|
|
23
|
+
Label: Cell Phone
|
|
24
|
+
Type: textinput
|
|
25
|
+
description:
|
|
26
|
+
Label: Description
|
|
27
|
+
Type: textarea
|
|
28
|
+
|
|
29
|
+
AttributeTypePicklists:
|
|
30
|
+
# these Picklists define values
|
|
31
|
+
# for artificially constructed fields
|
|
32
|
+
# that are really represent some other field's type
|
|
33
|
+
|
|
34
|
+
ObjectFields:
|
|
35
|
+
|
|
36
|
+
TitleFields:
|
|
37
|
+
# these fields are concatenated to show the record
|
|
38
|
+
# in the Index form
|
|
39
|
+
- lastname
|
|
40
|
+
- firstname
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Query_Fields:
|
|
2
|
+
# This is just a sample list of fields
|
|
3
|
+
# that are used in Query request
|
|
4
|
+
Id:
|
|
5
|
+
Label: Id
|
|
6
|
+
Type: id
|
|
7
|
+
|
|
8
|
+
AttributeTypePicklists:
|
|
9
|
+
# these Picklists define values
|
|
10
|
+
# for artificially constructed fields
|
|
11
|
+
# that are really represent some other field's type
|
|
12
|
+
|
|
13
|
+
ObjectFields:
|
|
14
|
+
# these are reference fields to the other objects
|
|
15
|
+
|
|
16
|
+
TitleFields:
|
|
17
|
+
# these fields are concatenated to show the record
|
|
18
|
+
# in the Index form
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Query_Fields:
|
|
2
|
+
# This is just a sample list of fields
|
|
3
|
+
# that are used in Query
|
|
4
|
+
leadid:
|
|
5
|
+
Label: Id
|
|
6
|
+
Type: id
|
|
7
|
+
firstname:
|
|
8
|
+
Label: First Name
|
|
9
|
+
Type: textinput
|
|
10
|
+
lastname:
|
|
11
|
+
Label: Last Name
|
|
12
|
+
Type: textinput
|
|
13
|
+
mobilephone:
|
|
14
|
+
Label: Cell Phone
|
|
15
|
+
Type: textinput
|
|
16
|
+
emailaddress1:
|
|
17
|
+
Label: E-mail
|
|
18
|
+
Type: textinput
|
|
19
|
+
companyname:
|
|
20
|
+
Label: Company
|
|
21
|
+
Type: textinput
|
|
22
|
+
jobtitle:
|
|
23
|
+
Label: Job Title
|
|
24
|
+
Type: textinput
|
|
25
|
+
estimatedvalue:
|
|
26
|
+
Label: Estimated Value
|
|
27
|
+
Type: textinput
|
|
28
|
+
estimatedclosedate:
|
|
29
|
+
Label: Estimated Close Date
|
|
30
|
+
Type: textinput
|
|
31
|
+
address1_country:
|
|
32
|
+
Label: Country
|
|
33
|
+
Type: textinput
|
|
34
|
+
address1_city:
|
|
35
|
+
Label: City
|
|
36
|
+
Type: textinput
|
|
37
|
+
address1_line1:
|
|
38
|
+
Label: Street Address
|
|
39
|
+
Type: textinput
|
|
40
|
+
|
|
41
|
+
AttributeTypePicklists:
|
|
42
|
+
# these Picklists define values
|
|
43
|
+
# for artificially constructed fields
|
|
44
|
+
# that are really represent some other field's type
|
|
45
|
+
|
|
46
|
+
ObjectFields:
|
|
47
|
+
# these are reference fields to the other objects
|
|
48
|
+
|
|
49
|
+
TitleFields:
|
|
50
|
+
# these fields are concatenated to show the record
|
|
51
|
+
# in the Index form
|
|
52
|
+
- lastname
|
|
53
|
+
- firstname
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Query_Fields:
|
|
2
|
+
# This is just a sample list of fields
|
|
3
|
+
# that are used in Query
|
|
4
|
+
opportunityid:
|
|
5
|
+
Label: Id
|
|
6
|
+
Type: id
|
|
7
|
+
name:
|
|
8
|
+
Label: Name
|
|
9
|
+
Type: textinput
|
|
10
|
+
description:
|
|
11
|
+
Label: Description
|
|
12
|
+
Type: textarea
|
|
13
|
+
estimatedvalue:
|
|
14
|
+
Label: Estimated Value
|
|
15
|
+
Type: textinput
|
|
16
|
+
closeprobability:
|
|
17
|
+
Label: Probability
|
|
18
|
+
Type: textinput
|
|
19
|
+
customerid:
|
|
20
|
+
Label: Customer
|
|
21
|
+
Type: textinput
|
|
22
|
+
customerid_attrtype:
|
|
23
|
+
Label: Customer Type
|
|
24
|
+
Type: Picklist
|
|
25
|
+
|
|
26
|
+
AttributeTypePicklists:
|
|
27
|
+
# these Picklists define values
|
|
28
|
+
# for artificially constructed fields
|
|
29
|
+
# that are really represent some other field's type
|
|
30
|
+
customerid_attrtype:
|
|
31
|
+
- account
|
|
32
|
+
- contact
|
|
33
|
+
|
|
34
|
+
ObjectFields:
|
|
35
|
+
# these are reference fields to the other objects
|
|
36
|
+
|
|
37
|
+
TitleFields:
|
|
38
|
+
# these fields are concatenated to show the record
|
|
39
|
+
# in the Index form
|
|
40
|
+
- name
|
|
41
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Application" do
|
|
4
|
+
it_should_behave_like "SpecHelper" do
|
|
5
|
+
def should_be_between(t,start,stop)
|
|
6
|
+
dt = DateTime.parse(t)
|
|
7
|
+
dt.should > DateTime.parse(start.to_s)
|
|
8
|
+
dt.should <= DateTime.parse(stop.to_s)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should authenticate" do
|
|
12
|
+
auth_info = RhoconnectAdapters::CRM::MsDynamics.load_auth_info(@test_user)
|
|
13
|
+
now = DateTime.now
|
|
14
|
+
should_be_between(auth_info['wlid_expires'],now,(now+(60 * 60 * 24)))
|
|
15
|
+
should_be_between(auth_info['crm_ticket_expires'],now,(now+(60 * 60 * 24)))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should not authenticate with wrong credentials" do
|
|
19
|
+
Application.should_receive(:warn).once.with('Can\'t authenticate user wrong_user: #<RuntimeError: RhoconnectAdapters::CRM::MsDynamics::WlidService error w/ IssueTicket: Authentication Failure (0x80041034): The specified member name is either invalid or empty. >')
|
|
20
|
+
Application.authenticate('wrong_user','wrong_password',nil).should be_false
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Account" do
|
|
4
|
+
it_should_behave_like "SpecHelper" do
|
|
5
|
+
before(:each) do
|
|
6
|
+
sample_data_file = File.join(File.dirname(__FILE__),'..','..','vendor','ms_dynamics','spec_data','Account.yml')
|
|
7
|
+
@sample_data = YAML.load_file(sample_data_file)['Account'] if sample_data_file and File.exist?(sample_data_file)
|
|
8
|
+
setup_test_for Account,@test_user
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
@ss.adapter.login
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
after(:each) do
|
|
16
|
+
@ss.adapter.logoff
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should process Account query" do
|
|
20
|
+
result = test_query
|
|
21
|
+
puts result.length.inspect
|
|
22
|
+
query_errors.should == {}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should process Account create" do
|
|
26
|
+
create_hash = @sample_data
|
|
27
|
+
result = test_create(create_hash)
|
|
28
|
+
puts result.inspect
|
|
29
|
+
create_hash['accountid'] = result
|
|
30
|
+
TestHelpers.created_records = { result => create_hash }
|
|
31
|
+
create_errors.should == {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should process Account update" do
|
|
35
|
+
TestHelpers.created_records.each do |key,value|
|
|
36
|
+
value['name'] = "Sample Update #{key.to_s}"
|
|
37
|
+
end
|
|
38
|
+
result = test_update(TestHelpers.created_records)
|
|
39
|
+
puts result.inspect
|
|
40
|
+
update_errors.should == {}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should process Account delete" do
|
|
44
|
+
result = test_delete(TestHelpers.created_records)
|
|
45
|
+
puts result.inspect
|
|
46
|
+
delete_errors.should == {}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Contact" do
|
|
4
|
+
it_should_behave_like "SpecHelper" do
|
|
5
|
+
before(:each) do
|
|
6
|
+
sample_data_file = File.join(File.dirname(__FILE__),'..','..','vendor','ms_dynamics','spec_data','Contact.yml')
|
|
7
|
+
@sample_data = YAML.load_file(sample_data_file)['Contact'] if sample_data_file and File.exist?(sample_data_file)
|
|
8
|
+
setup_test_for Contact,@test_user
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
@ss.adapter.login
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
after(:each) do
|
|
16
|
+
@ss.adapter.logoff
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should process Contact query" do
|
|
20
|
+
result = test_query
|
|
21
|
+
puts result.length.inspect
|
|
22
|
+
query_errors.should == {}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should process Contact create" do
|
|
26
|
+
create_hash = @sample_data
|
|
27
|
+
result = test_create(create_hash)
|
|
28
|
+
puts result.inspect
|
|
29
|
+
create_hash['contactid'] = result
|
|
30
|
+
TestHelpers.created_records = { result => create_hash }
|
|
31
|
+
create_errors.should == {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should process Contact update" do
|
|
35
|
+
TestHelpers.created_records.each do |key,value|
|
|
36
|
+
value['name'] = "Sample Update #{key.to_s}"
|
|
37
|
+
end
|
|
38
|
+
result = test_update(TestHelpers.created_records)
|
|
39
|
+
puts result.inspect
|
|
40
|
+
update_errors.should == {}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should process Contact delete" do
|
|
44
|
+
result = test_delete(TestHelpers.created_records)
|
|
45
|
+
puts result.inspect
|
|
46
|
+
delete_errors.should == {}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Lead" do
|
|
4
|
+
it_should_behave_like "SpecHelper" do
|
|
5
|
+
before(:each) do
|
|
6
|
+
sample_data_file = File.join(File.dirname(__FILE__),'..','..','vendor','ms_dynamics','spec_data','Lead.yml')
|
|
7
|
+
@sample_data = YAML.load_file(sample_data_file)['Lead'] if sample_data_file and File.exist?(sample_data_file)
|
|
8
|
+
setup_test_for Lead,@test_user
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
@ss.adapter.login
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
after(:each) do
|
|
16
|
+
@ss.adapter.logoff
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should process Lead query" do
|
|
20
|
+
result = test_query
|
|
21
|
+
puts result.length.inspect
|
|
22
|
+
query_errors.should == {}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should process Lead create" do
|
|
26
|
+
create_hash = @sample_data
|
|
27
|
+
result = test_create(create_hash)
|
|
28
|
+
puts result.inspect
|
|
29
|
+
create_hash['leadid'] = result
|
|
30
|
+
TestHelpers.created_records = { result => create_hash }
|
|
31
|
+
create_errors.should == {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should process Lead update" do
|
|
35
|
+
TestHelpers.created_records.each do |key,value|
|
|
36
|
+
value['name'] = "Sample Update #{key.to_s}"
|
|
37
|
+
end
|
|
38
|
+
result = test_update(TestHelpers.created_records)
|
|
39
|
+
puts result.inspect
|
|
40
|
+
update_errors.should == {}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should process Lead delete" do
|
|
44
|
+
result = test_delete(TestHelpers.created_records)
|
|
45
|
+
puts result.inspect
|
|
46
|
+
delete_errors.should == {}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Opportunity" do
|
|
4
|
+
it_should_behave_like "SpecHelper" do
|
|
5
|
+
before(:all) do
|
|
6
|
+
sample_data_file = File.join(File.dirname(__FILE__),'..','..','vendor','ms_dynamics','spec_data','Opportunity.yml')
|
|
7
|
+
@sample_data = YAML.load_file(sample_data_file)['Opportunity'] if sample_data_file and File.exist?(sample_data_file)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
before(:each) do
|
|
11
|
+
setup_test_for Opportunity,@test_user
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
before(:each) do
|
|
15
|
+
@ss.adapter.login
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
after(:each) do
|
|
19
|
+
@ss.adapter.logoff
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should process Opportunity query" do
|
|
23
|
+
result = test_query
|
|
24
|
+
puts result.length.inspect
|
|
25
|
+
query_errors.should == {}
|
|
26
|
+
|
|
27
|
+
# Opportunity cannot be created without a valid
|
|
28
|
+
# customerid (which is either a Contact or Account)
|
|
29
|
+
# so, we are using some already existing one
|
|
30
|
+
# for subsequent create/update/delete specs
|
|
31
|
+
result.each do |key, value|
|
|
32
|
+
@sample_data['customerid'] = value['customerid']
|
|
33
|
+
@sample_data['customerid_attrtype'] = value['customerid_attrtype']
|
|
34
|
+
break
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should process Opportunity create" do
|
|
39
|
+
create_hash = @sample_data
|
|
40
|
+
result = test_create(create_hash)
|
|
41
|
+
puts result.inspect
|
|
42
|
+
create_hash['opportunityid'] = result
|
|
43
|
+
TestHelpers.created_records = { result => create_hash }
|
|
44
|
+
create_errors.should == {}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should process Opportunity update" do
|
|
48
|
+
TestHelpers.created_records.each do |key,value|
|
|
49
|
+
value['name'] = "Sample Update #{key.to_s}"
|
|
50
|
+
end
|
|
51
|
+
result = test_update(TestHelpers.created_records)
|
|
52
|
+
puts result.inspect
|
|
53
|
+
update_errors.should == {}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should process Opportunity delete" do
|
|
57
|
+
result = test_delete(TestHelpers.created_records)
|
|
58
|
+
puts result.inspect
|
|
59
|
+
delete_errors.should == {}
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|