sepafm 0.0.1

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.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +8 -0
  6. data/README.md +236 -0
  7. data/Rakefile +10 -0
  8. data/lib/danske_get_bank_certificate_test.rb +15 -0
  9. data/lib/sepa/application_request.rb +182 -0
  10. data/lib/sepa/application_response.rb +123 -0
  11. data/lib/sepa/client.rb +79 -0
  12. data/lib/sepa/danske_testing/keys/danske_encryption.crt +24 -0
  13. data/lib/sepa/filedescriptor.rb +7 -0
  14. data/lib/sepa/filetypeservice.rb +6 -0
  15. data/lib/sepa/nordea_testing/keys/CSR.csr +0 -0
  16. data/lib/sepa/nordea_testing/keys/nordea.crt +27 -0
  17. data/lib/sepa/nordea_testing/keys/nordea.key +19 -0
  18. data/lib/sepa/nordea_testing/response/content_053.xml +998 -0
  19. data/lib/sepa/nordea_testing/response/content_054.xml +1 -0
  20. data/lib/sepa/nordea_testing/response/download_file_response.xml +14 -0
  21. data/lib/sepa/nordea_testing/response/download_filelist_response.xml +14 -0
  22. data/lib/sepa/nordea_testing/response/get_user_info_response.xml +14 -0
  23. data/lib/sepa/nordea_testing/response/upload_file_response.xml +14 -0
  24. data/lib/sepa/response.rb +177 -0
  25. data/lib/sepa/sender_verifier.rb +15 -0
  26. data/lib/sepa/signature.rb +7 -0
  27. data/lib/sepa/soap_builder.rb +395 -0
  28. data/lib/sepa/soap_danske.rb +47 -0
  29. data/lib/sepa/soap_nordea.rb +68 -0
  30. data/lib/sepa/userfiletype.rb +16 -0
  31. data/lib/sepa/version.rb +3 -0
  32. data/lib/sepa/wsdl/wsdl_danske.xml +234 -0
  33. data/lib/sepa/wsdl/wsdl_danske_cert.xml +280 -0
  34. data/lib/sepa/wsdl/wsdl_nordea.xml +234 -0
  35. data/lib/sepa/wsdl/wsdl_nordea_cert.xml +187 -0
  36. data/lib/sepa/xml_parser.rb +291 -0
  37. data/lib/sepa/xml_schemas/application_request.xsd +135 -0
  38. data/lib/sepa/xml_schemas/application_response.xsd +311 -0
  39. data/lib/sepa/xml_schemas/cert_application_request.xsd +107 -0
  40. data/lib/sepa/xml_schemas/danske_pki.xsd +334 -0
  41. data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-secext-1.0.xsd +195 -0
  42. data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-utility-1.0.xsd +108 -0
  43. data/lib/sepa/xml_schemas/soap.xsd +126 -0
  44. data/lib/sepa/xml_schemas/wsdl.xml +310 -0
  45. data/lib/sepa/xml_schemas/xml.xsd +287 -0
  46. data/lib/sepa/xml_schemas/xmldsig-core-schema.xsd +318 -0
  47. data/lib/sepa/xml_templates/application_request/create_certificate.xml +10 -0
  48. data/lib/sepa/xml_templates/application_request/danske_get_bank_certificate.xml +10 -0
  49. data/lib/sepa/xml_templates/application_request/download_file.xml +32 -0
  50. data/lib/sepa/xml_templates/application_request/download_file_list.xml +29 -0
  51. data/lib/sepa/xml_templates/application_request/get_certificate.xml +10 -0
  52. data/lib/sepa/xml_templates/application_request/get_user_info.xml +26 -0
  53. data/lib/sepa/xml_templates/application_request/upload_file.xml +29 -0
  54. data/lib/sepa/xml_templates/soap/create_certificate.xml +15 -0
  55. data/lib/sepa/xml_templates/soap/danske_get_bank_certificate.xml +14 -0
  56. data/lib/sepa/xml_templates/soap/download_file.xml +16 -0
  57. data/lib/sepa/xml_templates/soap/download_file_list.xml +16 -0
  58. data/lib/sepa/xml_templates/soap/get_certificate.xml +13 -0
  59. data/lib/sepa/xml_templates/soap/get_user_info.xml +16 -0
  60. data/lib/sepa/xml_templates/soap/header.xml +37 -0
  61. data/lib/sepa/xml_templates/soap/upload_file.xml +16 -0
  62. data/lib/sepa.rb +21 -0
  63. data/lib/sepa_client_testing_mika.rb +32 -0
  64. data/lib/sepa_client_testing_tiere.rb +80 -0
  65. data/sepa.gemspec +29 -0
  66. data/test/sepa/application_request_test.rb +423 -0
  67. data/test/sepa/application_response_test.rb +238 -0
  68. data/test/sepa/cert_application_request_test.rb +99 -0
  69. data/test/sepa/client_test.rb +425 -0
  70. data/test/sepa/danske_test_keys/danskeroot.pem +25 -0
  71. data/test/sepa/danske_test_keys/encryption_pkcs.csr +0 -0
  72. data/test/sepa/danske_test_keys/signing_key.pem +27 -0
  73. data/test/sepa/danske_test_keys/signing_pkcs.csr +0 -0
  74. data/test/sepa/nordea_cert_request_soap_builder_test.rb +112 -0
  75. data/test/sepa/nordea_generic_soap_builder_test.rb +427 -0
  76. data/test/sepa/nordea_test_keys/nordea.crt +27 -0
  77. data/test/sepa/nordea_test_keys/nordea.key +19 -0
  78. data/test/sepa/nordea_test_keys/root_cert.cer +0 -0
  79. data/test/sepa/nordea_test_keys/testcert.csr +0 -0
  80. data/test/sepa/response_test.rb +269 -0
  81. data/test/sepa/sepa_test.rb +20 -0
  82. data/test/sepa/test_files/invalid.wsdl +1 -0
  83. data/test/sepa/test_files/test_responses/df.xml +20 -0
  84. data/test/sepa/test_files/test_responses/dfl.xml +20 -0
  85. data/test/sepa/test_files/test_responses/gui.xml +20 -0
  86. data/test/sepa/test_files/test_responses/uf.xml +20 -0
  87. data/test/sepa/user_file_type_test.rb +21 -0
  88. data/test/sepa/xml_parser_test.rb +73 -0
  89. data/test/test_helper.rb +9 -0
  90. metadata +256 -0
@@ -0,0 +1,423 @@
1
+ require File.expand_path('../../test_helper.rb', __FILE__)
2
+
3
+ class TestApplicationRequest < MiniTest::Test
4
+ def setup
5
+ keys_path = File.expand_path('../nordea_test_keys', __FILE__)
6
+
7
+ @xml_templates_path = File.expand_path(
8
+ '../../../lib/sepa/xml_templates/application_request', __FILE__
9
+ )
10
+
11
+ @schemas_path = File.expand_path('../../../lib/sepa/xml_schemas',__FILE__)
12
+
13
+ @private_key = OpenSSL::PKey::RSA.new(File.read("#{keys_path}/nordea.key"))
14
+ @cert = OpenSSL::X509::Certificate.new(File.read("#{keys_path}/nordea.crt"))
15
+ certplain = "-----BEGIN CERTIFICATE-----
16
+ MIIDwTCCAqmgAwIBAgIEAX1JuTANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJT
17
+ RTEeMBwGA1UEChMVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMR8wHQYDVQQDExZOb3Jk
18
+ ZWEgQ29ycG9yYXRlIENBIDAxMRQwEgYDVQQFEws1MTY0MDYtMDEyMDAeFw0xMzA1
19
+ MDIxMjI2MzRaFw0xNTA1MDIxMjI2MzRaMEQxCzAJBgNVBAYTAkZJMSAwHgYDVQQD
20
+ DBdOb3JkZWEgRGVtbyBDZXJ0aWZpY2F0ZTETMBEGA1UEBRMKNTc4MDg2MDIzODCB
21
+ nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwtFEfAtbJuGzQwwRumZkvYh2BjGY
22
+ VsAMUeiKtOne3bZSeisfCq+TXqL1gI9LofyeAQ9I/sDm6tL80yrD5iaSUqVm6A73
23
+ 9MsmpW/iyZcVf7ms8xAN51ESUgN6akwZCU9pH62ngJDj2gUsktY0fpsoVsARdrvO
24
+ Fk0fTSUXKWd6LbcCAwEAAaOCAR0wggEZMAkGA1UdEwQCMAAwEQYDVR0OBAoECEBw
25
+ 2cj7+XMAMBMGA1UdIAQMMAowCAYGKoVwRwEDMBMGA1UdIwQMMAqACEALddbbzwun
26
+ MDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3Aubm9yZGVh
27
+ LnNlL0NDQTAxMA4GA1UdDwEB/wQEAwIFoDCBhQYDVR0fBH4wfDB6oHigdoZ0bGRh
28
+ cCUzQS8vbGRhcC5uYi5zZS9jbiUzRE5vcmRlYStDb3Jwb3JhdGUrQ0ErMDElMkNv
29
+ JTNETm9yZGVhK0JhbmsrQUIrJTI4cHVibCUyOSUyQ2MlM0RTRSUzRmNlcnRpZmlj
30
+ YXRlcmV2b2NhdGlvbmxpc3QwDQYJKoZIhvcNAQEFBQADggEBACLUPB1Gmq6286/s
31
+ ROADo7N+w3eViGJ2fuOTLMy4R0UHOznKZNsuk4zAbS2KycbZsE5py4L8o+IYoaS8
32
+ 8YHtEeckr2oqHnPpz/0Eg7wItj8Ad+AFWJqzbn6Hu/LQhlnl5JEzXzl3eZj9oiiJ
33
+ 1q/2CGXvFomY7S4tgpWRmYULtCK6jode0NhgNnAgOI9uy76pSS16aDoiQWUJqQgV
34
+ ydowAnqS9h9aQ6gedwbOdtkWmwKMDVXU6aRz9Gvk+JeYJhtpuP3OPNGbbC5L7NVd
35
+ no+B6AtwxmG3ozd+mPcMeVuz6kKLAmQyIiBSrRNa5OrTkq/CUzxO9WUgTnm/Sri7
36
+ zReR6mU=
37
+ -----END CERTIFICATE-----"
38
+ pkeyplain = "-----BEGIN PRIVATE KEY-----
39
+ MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMLRRHwLWybhs0MM
40
+ EbpmZL2IdgYxmFbADFHoirTp3t22UnorHwqvk16i9YCPS6H8ngEPSP7A5urS/NMq
41
+ w+YmklKlZugO9/TLJqVv4smXFX+5rPMQDedRElIDempMGQlPaR+tp4CQ49oFLJLW
42
+ NH6bKFbAEXa7zhZNH00lFylnei23AgMBAAECgYEAqt912/7x4jaQTrxlSELLFVp9
43
+ eo1BesVTiPwXvPpsGbbyvGjZ/ztkXNs9zZbh1aCGzZMkiR2U7F5GlsiprlIif4cF
44
+ 6Xz7rCjaAs7iDRt9PjhjVuqNGR2I+VIIlbQ9XWFJ3lJFW3v7TIZ8JbLnn0XOFz+Z
45
+ BBSSGTK1zTNh4TBQtjECQQDe5M3uu9m4RwSw9R6GaDw/IFQZgr0oWSv0WIjRwvwW
46
+ nFnSX2lbkNAjulP0daGsmn7vxIpqZxPxwcrU4wFqTF5dAkEA38DnbCm3YfogzwLH
47
+ Nre2hBmGqjWarhtxqtRarrkgnmOd8W0Z1Hb1dSHrliUSVSrINbK5ZdEV15Rpu7VD
48
+ OePzIwJAPMslS+8alANyyR0iJUC65fDYX1jkZOPldDDNqIDJJxWf/hwd7WaTDpuc
49
+ mHmZDi3ZX2Y45oqUywSzYNtFoIuR1QJAZYUZuyqmSK77SdGB36K1DfSi9AFEQDC1
50
+ fwPAbTwTv6mFFPAiYxLiRZXxVPtW+QtjMXH4ymh2V4y/+GnCqbZyLwJBAJQSDAME
51
+ Sn4Uz7Zjk3UrBIbMYEv0u2mcCypwsb0nGE5/gzDPjGE9cxWW+rXARIs+sNQVClnh
52
+ 45nhdfYxOjgYff0=
53
+ -----END PRIVATE KEY-----"
54
+ @params = {
55
+ bank: :nordea,
56
+ private_key_plain: pkeyplain,
57
+ cert_plain: certplain,
58
+ command: :download_file,
59
+ customer_id: '11111111',
60
+ environment: 'PRODUCTION',
61
+ status: 'NEW',
62
+ target_id: '11111111A1',
63
+ language: 'FI',
64
+ file_type: 'TITO',
65
+ content: Base64.encode64("haisuli"),
66
+ file_reference: "11111111A12006030329501800000014"
67
+ }
68
+
69
+ #@ar_file = Sepa::ApplicationRequest.new(@params)
70
+ @ar_file = Sepa::SoapBuilder.new(@params).get_ar_as_base64
71
+
72
+ @params[:command] = :get_user_info
73
+ #@ar_get = Sepa::ApplicationRequest.new(@params)
74
+ @ar_get = Sepa::SoapBuilder.new(@params).get_ar_as_base64
75
+
76
+ @params[:command] = :download_file_list
77
+ #@ar_list = Sepa::ApplicationRequest.new(@params)
78
+ @ar_list = Sepa::SoapBuilder.new(@params).get_ar_as_base64
79
+
80
+ @params[:command] = :upload_file
81
+ #@ar_up = Sepa::ApplicationRequest.new(@params)
82
+ @ar_up = Sepa::SoapBuilder.new(@params).get_ar_as_base64
83
+
84
+ @doc_file = Nokogiri::XML(Base64.decode64(@ar_file))
85
+ @doc_get = Nokogiri::XML(Base64.decode64(@ar_get))
86
+ @doc_list = Nokogiri::XML(Base64.decode64(@ar_list))
87
+ @doc_up = Nokogiri::XML(Base64.decode64(@ar_up))
88
+ end
89
+
90
+ # Just to make sure that the xml templates are unmodified because
91
+ # the application logic is designed for exactly these templates
92
+ def test_xml_templates_are_unmodified
93
+ sha1 = OpenSSL::Digest::SHA1.new
94
+
95
+ get_user_info_template = File.read(
96
+ "#{@xml_templates_path}/get_user_info.xml"
97
+ )
98
+
99
+ download_file_list_template = File.read(
100
+ "#{@xml_templates_path}/download_file_list.xml"
101
+ )
102
+
103
+ download_file_template = File.read(
104
+ "#{@xml_templates_path}/download_file.xml"
105
+ )
106
+
107
+ upload_file_template = File.read(
108
+ "#{@xml_templates_path}/upload_file.xml"
109
+ )
110
+
111
+ get_user_info_digest = Base64.encode64(
112
+ sha1.digest(get_user_info_template)
113
+ ).strip
114
+
115
+ sha1.reset
116
+
117
+ download_file_list_digest = Base64.encode64(
118
+ sha1.digest(download_file_list_template)
119
+ ).strip
120
+
121
+ sha1.reset
122
+
123
+ download_file_digest = sha1.digest(download_file_template)
124
+
125
+ sha1.reset
126
+
127
+ upload_file_digest = sha1.digest(upload_file_template)
128
+
129
+ assert_equal get_user_info_digest, "LW5J5R7SnPFPurAa2pM7weTWL1Y="
130
+
131
+ assert_equal download_file_list_digest.strip,
132
+ "dYtf4lOP1TXfXPVjYLvaTozhVrg="
133
+
134
+ assert_equal Base64.encode64(download_file_digest).strip,
135
+ "lY+8u+BhXlQmUyQiOiXcUfCUikc="
136
+
137
+ assert_equal Base64.encode64(upload_file_digest).strip,
138
+ "zRQTrNHkq4OLSX3u3ogxU05RJsI="
139
+ end
140
+
141
+ def test_schemas_are_unmodified
142
+ sha1 = OpenSSL::Digest::SHA1.new
143
+
144
+ ar_schema = File.read(
145
+ "#{@schemas_path}/application_request.xsd"
146
+ )
147
+
148
+ xmldsig_schema = File.read(
149
+ "#{@schemas_path}/xmldsig-core-schema.xsd"
150
+ )
151
+
152
+ ar_schema_digest = sha1.digest(ar_schema)
153
+
154
+ sha1.reset
155
+
156
+ xmldsig_schema_digest = sha1.digest(xmldsig_schema)
157
+
158
+ assert_equal Base64.encode64(ar_schema_digest).strip,
159
+ "1O24A7+/6S7CFYVlhH1jEZh1ARs="
160
+
161
+ assert_equal Base64.encode64(xmldsig_schema_digest).strip,
162
+ "bmG0+2KykgkLeWsXsl6CFbyo4Yc="
163
+ end
164
+
165
+ def test_ar_should_initialize_with_proper_params
166
+ assert Sepa::SoapBuilder.new(@params)
167
+ end
168
+
169
+ def test_should_get_key_error_if_private_key_plain_missing
170
+ @params.delete(:private_key_plain)
171
+
172
+ assert_raises(ArgumentError) do
173
+ Sepa::SoapBuilder.new(@params)
174
+ end
175
+ end
176
+
177
+ def test_should_get_key_error_if_cert_plain_missing
178
+ @params.delete(:cert_plain)
179
+
180
+ assert_raises(ArgumentError) do
181
+ Sepa::SoapBuilder.new(@params)
182
+ end
183
+ end
184
+
185
+ def test_should_get_key_error_if_command_missing
186
+ @params.delete(:command)
187
+
188
+ assert_raises(ArgumentError) do
189
+ Sepa::SoapBuilder.new(@params)
190
+ end
191
+ end
192
+
193
+ def test_should_get_key_error_if_customer_id_missing
194
+ @params.delete(:customer_id)
195
+
196
+ assert_raises(ArgumentError) do
197
+ Sepa::SoapBuilder.new(@params)
198
+ end
199
+ end
200
+
201
+ def test_should_get_key_error_if_environment_missing
202
+ @params.delete(:environment)
203
+
204
+ assert_raises(ArgumentError) do
205
+ Sepa::SoapBuilder.new(@params)
206
+ end
207
+ end
208
+
209
+ def test_should_have_customer_id_set_in_with_all_commands
210
+ assert_equal @doc_file.at_css("CustomerId").content, @params[:customer_id]
211
+ assert_equal @doc_get.at_css("CustomerId").content, @params[:customer_id]
212
+ assert_equal @doc_list.at_css("CustomerId").content, @params[:customer_id]
213
+ assert_equal @doc_up.at_css("CustomerId").content, @params[:customer_id]
214
+ end
215
+
216
+ def test_should_have_timestamp_set_properly_with_all_commands
217
+ timestamp_file = Time.strptime(@doc_file.at_css("Timestamp").content,
218
+ '%Y-%m-%dT%H:%M:%S%z')
219
+
220
+ timestamp_get = Time.strptime(@doc_get.at_css("Timestamp").content,
221
+ '%Y-%m-%dT%H:%M:%S%z')
222
+
223
+ timestamp_list = Time.strptime(@doc_list.at_css("Timestamp").content,
224
+ '%Y-%m-%dT%H:%M:%S%z')
225
+
226
+ timestamp_up = Time.strptime(@doc_up.at_css("Timestamp").content,
227
+ '%Y-%m-%dT%H:%M:%S%z')
228
+
229
+ assert timestamp_file <= Time.now && timestamp_file > (Time.now - 60),
230
+ "Timestamp was not set correctly"
231
+
232
+ assert timestamp_get <= Time.now && timestamp_get > (Time.now - 60),
233
+ "Timestamp was not set correctly"
234
+
235
+ assert timestamp_list <= Time.now && timestamp_list > (Time.now - 60),
236
+ "Timestamp was not set correctly"
237
+
238
+ assert timestamp_up <= Time.now && timestamp_up > (Time.now - 60),
239
+ "Timestamp was not set correctly"
240
+ end
241
+
242
+ def test_should_have_command_set_when_get_user_info
243
+
244
+ assert_equal @doc_get.at_css("Command").content, "GetUserInfo"
245
+ end
246
+
247
+ def test_should_have_command_set_when_download_file_list
248
+ assert_equal @doc_list.at_css("Command").content, "DownloadFileList"
249
+ end
250
+
251
+ def test_should_have_command_set_when_download_file
252
+ assert_equal @doc_file.at_css("Command").content, "DownloadFile"
253
+ end
254
+
255
+ def test_should_have_command_set_when_upload_file
256
+ assert_equal @doc_up.at_css("Command").content, "UploadFile"
257
+ end
258
+
259
+ def test_should_have_environment_set_with_all_commands
260
+ assert_equal @doc_file.at_css("Environment").content, @params[:environment]
261
+ assert_equal @doc_get.at_css("Environment").content, @params[:environment]
262
+ assert_equal @doc_list.at_css("Environment").content, @params[:environment]
263
+ assert_equal @doc_up.at_css("Environment").content, @params[:environment]
264
+ end
265
+
266
+ def test_should_have_software_id_set_with_all_commands
267
+ assert_equal @doc_file.at_css("SoftwareId").content,
268
+ "Sepa Transfer Library version " + Sepa::VERSION
269
+
270
+ assert_equal @doc_get.at_css("SoftwareId").content,
271
+ "Sepa Transfer Library version " + Sepa::VERSION
272
+
273
+ assert_equal @doc_list.at_css("SoftwareId").content,
274
+ "Sepa Transfer Library version " + Sepa::VERSION
275
+
276
+ assert_equal @doc_up.at_css("SoftwareId").content,
277
+ "Sepa Transfer Library version " + Sepa::VERSION
278
+ end
279
+
280
+ def test_should_have_status_set_when_download_file_list
281
+ assert_equal @doc_list.at_css("Status").content, @params[:status]
282
+ end
283
+
284
+ def test_should_have_status_set_when_download_file
285
+ assert_equal @doc_file.at_css("Status").content, @params[:status]
286
+ end
287
+
288
+ def test_should_not_have_status_set_when_get_user_info
289
+ refute @doc_get.at_css("Status")
290
+ end
291
+
292
+ def test_should_not_have_status_set_when_upload_file
293
+ refute @doc_up.at_css("Status")
294
+ end
295
+
296
+ def test_should_have_target_id_set_when_download_file_list
297
+ assert_equal @doc_list.at_css("TargetId").content, @params[:target_id]
298
+ end
299
+
300
+ def test_should_have_target_id_set_when_download_file
301
+ assert_equal @doc_file.at_css("TargetId").content, @params[:target_id]
302
+ end
303
+
304
+ def test_should_not_have_target_id_set_when_get_user_info
305
+ refute @doc_get.at_css("TargetId")
306
+ end
307
+
308
+ def test_should_have_file_type_set_when_download_file_list
309
+ assert_equal @doc_list.at_css("FileType").content, @params[:file_type]
310
+ end
311
+
312
+ def test_should_have_file_type_set_when_download_file
313
+ assert_equal @doc_file.at_css("FileType").content, @params[:file_type]
314
+ end
315
+
316
+ def test_should_have_file_type_set_when_upload_file
317
+ assert_equal @doc_up.at_css("FileType").content, @params[:file_type]
318
+ end
319
+
320
+ def test_should_not_have_file_type_set_when_get_user_info
321
+ refute @doc_get.at_css("FileType")
322
+ end
323
+
324
+ def test_should_have_file_reference_set_when_download_file
325
+ assert_equal @doc_file.at_css("FileReference").content,
326
+ @params[:file_reference]
327
+ end
328
+
329
+ def test_should_not_have_file_ref_when_download_file_list
330
+ refute @doc_list.at_css("FileReference")
331
+ end
332
+
333
+ def test_should_not_have_file_ref_when_get_user_info
334
+ refute @doc_get.at_css("FileReference")
335
+ end
336
+
337
+ def test_should_not_have_file_ref_when_upload_file
338
+ refute @doc_up.at_css("FileReference")
339
+ end
340
+
341
+ def test_should_have_content_when_upload_file
342
+ assert_equal @doc_up.at_css("Content").content,
343
+ Base64.encode64(@params[:content])
344
+ end
345
+
346
+ def test_should_not_have_content_when_download_file_list
347
+ refute @doc_list.at_css("Content")
348
+ end
349
+
350
+ def test_should_not_have_content_when_download_file
351
+ refute @doc_file.at_css("Content")
352
+ end
353
+
354
+ def test_should_not_have_content_when_get_user_info
355
+ refute @doc_get.at_css("Content")
356
+ end
357
+
358
+ def test_should_raise_argument_error_with_invalid_command
359
+ assert_raises(ArgumentError) do
360
+ @params[:command] = :wrong_kind_of_command
361
+ ar = Sepa::ApplicationRequest.new(@params)
362
+ doc = ar.get_as_base64
363
+ end
364
+ end
365
+
366
+ def test_digest_is_calculatd_correctly
367
+ calculated_digest = @doc_file.at_css(
368
+ "dsig|DigestValue", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
369
+ ).content
370
+
371
+ # Remove signature for calculating digest
372
+ @doc_file.at_css(
373
+ "dsig|Signature", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
374
+ ).remove
375
+
376
+ # Calculate digest
377
+ sha1 = OpenSSL::Digest::SHA1.new
378
+ actual_digest = Base64.encode64(sha1.digest(@doc_file.canonicalize))
379
+
380
+ # And then make sure the two are equal
381
+ assert_equal calculated_digest.strip, actual_digest.strip
382
+ end
383
+
384
+ def test_signature_is_constructed_correctly
385
+ #private_key = @params.fetch(:private_key)
386
+
387
+ signed_info_node = @doc_file.at_css(
388
+ "dsig|SignedInfo", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#')
389
+
390
+ # The value of the signature node in the constructed ar
391
+ calculated_signature = @doc_file.at_css(
392
+ "dsig|SignatureValue", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
393
+ ).content
394
+
395
+ # Calculate the actual signature
396
+ sha1 = OpenSSL::Digest::SHA1.new
397
+ actual_signature = Base64.encode64(@private_key.sign(
398
+ sha1, signed_info_node.canonicalize))
399
+
400
+ # And then of course assert the two are equal
401
+ assert_equal calculated_signature, actual_signature
402
+ end
403
+
404
+ def test_certificate_is_added_correctly
405
+ added_cert = @doc_file.at_css(
406
+ "dsig|X509Certificate", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
407
+ ).content
408
+
409
+ actual_cert = @params.fetch(:cert).to_s
410
+ actual_cert = actual_cert.split('-----BEGIN CERTIFICATE-----')[1]
411
+ actual_cert = actual_cert.split('-----END CERTIFICATE-----')[0]
412
+ actual_cert.gsub!(/\s+/, "")
413
+
414
+ assert_equal added_cert, actual_cert
415
+ end
416
+
417
+ def test_should_validate_against_schema
418
+ Dir.chdir(@schemas_path) do
419
+ xsd = Nokogiri::XML::Schema(IO.read('application_request.xsd'))
420
+ assert xsd.valid?(@doc_file)
421
+ end
422
+ end
423
+ end
@@ -0,0 +1,238 @@
1
+ require File.expand_path('../../test_helper.rb', __FILE__)
2
+
3
+ class ApplicationResponseTest < MiniTest::Test
4
+ def setup
5
+ keys_path = File.expand_path('../nordea_test_keys', __FILE__)
6
+
7
+ @root_cert = OpenSSL::X509::Certificate.new File.read(
8
+ "#{keys_path}/root_cert.cer"
9
+ )
10
+
11
+ @not_root_cert = OpenSSL::X509::Certificate.new File.read(
12
+ "#{keys_path}/nordea.crt"
13
+ )
14
+
15
+ responses_path = File.expand_path('../test_files/test_responses', __FILE__)
16
+
17
+ @dfl = Nokogiri::XML(File.read("#{responses_path}/dfl.xml"))
18
+ @dfl = Sepa::Response.new(@dfl).application_response
19
+
20
+ @uf = Nokogiri::XML(File.read("#{responses_path}/uf.xml"))
21
+ @uf = Sepa::Response.new(@uf).application_response
22
+
23
+ @df = Nokogiri::XML(File.read("#{responses_path}/df.xml"))
24
+ @df = Sepa::Response.new(@df).application_response
25
+
26
+ @gui = Nokogiri::XML(File.read("#{responses_path}/gui.xml"))
27
+ @gui = Sepa::Response.new(@gui).application_response
28
+
29
+ @dfl_ar = Sepa::ApplicationResponse.new(@dfl)
30
+ @uf_ar = Sepa::ApplicationResponse.new(@uf)
31
+ @df_ar = Sepa::ApplicationResponse.new(@df)
32
+ @gui_ar = Sepa::ApplicationResponse.new(@gui)
33
+ end
34
+
35
+ def test_should_initialize_with_proper_params
36
+ assert Sepa::ApplicationResponse.new(@dfl)
37
+ assert Sepa::ApplicationResponse.new(@uf)
38
+ assert Sepa::ApplicationResponse.new(@df)
39
+ assert Sepa::ApplicationResponse.new(@gui)
40
+ end
41
+
42
+ def test_should_complain_if_initialized_with_something_not_nokogiri_xml
43
+ assert_raises(ArgumentError) { Sepa::ApplicationResponse.new("Jees") }
44
+ end
45
+
46
+ def test_should_complain_if_ar_not_valid_against_schema
47
+ assert_raises(ArgumentError) do
48
+ Sepa::ApplicationResponse.new(Nokogiri::XML("<ar>text</ar>"))
49
+ end
50
+ end
51
+
52
+ def test_proper_dfl_hash_check_should_verify
53
+ assert @dfl_ar.hashes_match?
54
+ end
55
+
56
+ def test_proper_uf_hash_check_should_verify
57
+ assert @uf_ar.hashes_match?
58
+ end
59
+
60
+ def test_proper_df_hash_check_should_verify
61
+ assert @df_ar.hashes_match?
62
+ end
63
+
64
+ def test_proper_gui_hash_check_should_verify
65
+ assert @gui_ar.hashes_match?
66
+ end
67
+
68
+ def test_invalid_dfl_hash_check_should_not_verify
69
+ customer_id_node = @dfl.at_css('c2b|CustomerId')
70
+ customer_id_node.content = customer_id_node.content[0..-2]
71
+
72
+ refute Sepa::ApplicationResponse.new(@dfl).hashes_match?
73
+ end
74
+
75
+ def test_invalid_uf_hash_check_should_not_verify
76
+ timestamp_node = @uf.at_css('c2b|Timestamp')
77
+ timestamp_node.content = Time.now.iso8601
78
+
79
+ refute Sepa::ApplicationResponse.new(@uf).hashes_match?
80
+ end
81
+
82
+ def test_invalid_df_hash_check_should_not_verify
83
+ digest_value_node = @df.at_css(
84
+ 'xmlns|DigestValue',
85
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
86
+ )
87
+
88
+ digest_value_node.content = digest_value_node.content[4..-1]
89
+
90
+ refute Sepa::ApplicationResponse.new(@df).hashes_match?
91
+ end
92
+
93
+ def test_invalid_gui_hash_check_should_not_verify
94
+ digest_value_node = @gui.at_css(
95
+ 'xmlns|DigestValue',
96
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
97
+ )
98
+
99
+ digest_value_node.content = '1234' + digest_value_node.content
100
+
101
+ refute Sepa::ApplicationResponse.new(@gui).hashes_match?
102
+ end
103
+
104
+ def test_proper_dfl_signature_should_verify
105
+ assert @dfl_ar.signature_is_valid?
106
+ end
107
+
108
+ def test_proper_uf_signature_should_verify
109
+ assert @uf_ar.signature_is_valid?
110
+ end
111
+
112
+ def test_proper_df_signature_should_verify
113
+ assert @df_ar.signature_is_valid?
114
+ end
115
+
116
+ def test_proper_gui_signature_should_verify
117
+ assert @gui_ar.signature_is_valid?
118
+ end
119
+
120
+ def test_corrupted_signature_in_dfl_should_fail_signature_verification
121
+ signature_node = @dfl.at_css(
122
+ 'xmlns|SignatureValue',
123
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
124
+ )
125
+
126
+ signature_node.content = signature_node.content[4..-1]
127
+
128
+ refute Sepa::ApplicationResponse.new(@dfl).signature_is_valid?
129
+ end
130
+
131
+ def test_corrupted_signature_in_uf_should_fail_signature_verification
132
+ signature_node = @uf.at_css(
133
+ 'xmlns|SignatureValue',
134
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
135
+ )
136
+
137
+ signature_node.content = signature_node.content[0..-5]
138
+
139
+ refute Sepa::ApplicationResponse.new(@uf).signature_is_valid?
140
+ end
141
+
142
+ def test_corrupted_signature_in_df_should_fail_signature_verification
143
+ signature_node = @df.at_css(
144
+ 'xmlns|SignatureValue',
145
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
146
+ )
147
+
148
+ signature_node.content = 'a' + signature_node.content[1..-1]
149
+
150
+ refute Sepa::ApplicationResponse.new(@df).signature_is_valid?
151
+ end
152
+
153
+ def test_corrupted_signature_in_gui_should_fail_signature_verification
154
+ signature_node = @gui.at_css(
155
+ 'xmlns|SignatureValue',
156
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
157
+ )
158
+
159
+ signature_node.content = 'zombi' + signature_node.content[1..-1]
160
+
161
+ refute Sepa::ApplicationResponse.new(@gui).signature_is_valid?
162
+ end
163
+
164
+ def test_should_raise_error_if_certificate_corrupted_in_dfl
165
+ cert_node = @dfl.at_css(
166
+ 'xmlns|X509Certificate',
167
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
168
+ )
169
+
170
+ cert_node.content = cert_node.content[0..-5]
171
+
172
+ assert_raises(OpenSSL::X509::CertificateError) do
173
+ Sepa::ApplicationResponse.new(@dfl).certificate
174
+ end
175
+ end
176
+
177
+ def test_should_raise_error_if_certificate_corrupted_in_uf
178
+ cert_node = @uf.at_css(
179
+ 'xmlns|X509Certificate',
180
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
181
+ )
182
+
183
+ cert_node.content = cert_node.content[4..-1]
184
+
185
+ assert_raises(OpenSSL::X509::CertificateError) do
186
+ Sepa::ApplicationResponse.new(@uf).certificate
187
+ end
188
+ end
189
+
190
+ def test_should_raise_error_if_certificate_corrupted_in_df
191
+ cert_node = @df.at_css(
192
+ 'xmlns|X509Certificate',
193
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
194
+ )
195
+
196
+ cert_node.content = "n5iw#{cert_node.content}"
197
+
198
+ assert_raises(OpenSSL::X509::CertificateError) do
199
+ Sepa::ApplicationResponse.new(@df).certificate
200
+ end
201
+ end
202
+
203
+ def test_should_raise_error_if_certificate_corrupted_in_gui
204
+ cert_node = @gui.at_css(
205
+ 'xmlns|X509Certificate',
206
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
207
+ )
208
+
209
+ cert_node.content = Base64.encode64('voivoi')
210
+
211
+ assert_raises(OpenSSL::X509::CertificateError) do
212
+ Sepa::ApplicationResponse.new(@gui).certificate
213
+ end
214
+ end
215
+
216
+ def test_cert_should_be_trusted_with_correct_root_cert
217
+ assert @dfl_ar.cert_is_trusted?(@root_cert)
218
+ assert @uf_ar.cert_is_trusted?(@root_cert)
219
+ assert @df_ar.cert_is_trusted?(@root_cert)
220
+ assert @gui_ar.cert_is_trusted?(@root_cert)
221
+ end
222
+
223
+ def test_dfl_should_fail_if_wrong_root_cert
224
+ assert_raises(SecurityError) { @dfl_ar.cert_is_trusted?(@not_root_cert) }
225
+ end
226
+
227
+ def test_uf_should_fail_if_wrong_root_cert
228
+ assert_raises(SecurityError) { @uf_ar.cert_is_trusted?(@not_root_cert) }
229
+ end
230
+
231
+ def test_df_should_fail_if_wrong_root_cert
232
+ assert_raises(SecurityError) { @df_ar.cert_is_trusted?(@not_root_cert) }
233
+ end
234
+
235
+ def test_gui_should_fail_if_wrong_root_cert
236
+ assert_raises(SecurityError) { @gui_ar.cert_is_trusted?(@not_root_cert) }
237
+ end
238
+ end