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.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE +8 -0
- data/README.md +236 -0
- data/Rakefile +10 -0
- data/lib/danske_get_bank_certificate_test.rb +15 -0
- data/lib/sepa/application_request.rb +182 -0
- data/lib/sepa/application_response.rb +123 -0
- data/lib/sepa/client.rb +79 -0
- data/lib/sepa/danske_testing/keys/danske_encryption.crt +24 -0
- data/lib/sepa/filedescriptor.rb +7 -0
- data/lib/sepa/filetypeservice.rb +6 -0
- data/lib/sepa/nordea_testing/keys/CSR.csr +0 -0
- data/lib/sepa/nordea_testing/keys/nordea.crt +27 -0
- data/lib/sepa/nordea_testing/keys/nordea.key +19 -0
- data/lib/sepa/nordea_testing/response/content_053.xml +998 -0
- data/lib/sepa/nordea_testing/response/content_054.xml +1 -0
- data/lib/sepa/nordea_testing/response/download_file_response.xml +14 -0
- data/lib/sepa/nordea_testing/response/download_filelist_response.xml +14 -0
- data/lib/sepa/nordea_testing/response/get_user_info_response.xml +14 -0
- data/lib/sepa/nordea_testing/response/upload_file_response.xml +14 -0
- data/lib/sepa/response.rb +177 -0
- data/lib/sepa/sender_verifier.rb +15 -0
- data/lib/sepa/signature.rb +7 -0
- data/lib/sepa/soap_builder.rb +395 -0
- data/lib/sepa/soap_danske.rb +47 -0
- data/lib/sepa/soap_nordea.rb +68 -0
- data/lib/sepa/userfiletype.rb +16 -0
- data/lib/sepa/version.rb +3 -0
- data/lib/sepa/wsdl/wsdl_danske.xml +234 -0
- data/lib/sepa/wsdl/wsdl_danske_cert.xml +280 -0
- data/lib/sepa/wsdl/wsdl_nordea.xml +234 -0
- data/lib/sepa/wsdl/wsdl_nordea_cert.xml +187 -0
- data/lib/sepa/xml_parser.rb +291 -0
- data/lib/sepa/xml_schemas/application_request.xsd +135 -0
- data/lib/sepa/xml_schemas/application_response.xsd +311 -0
- data/lib/sepa/xml_schemas/cert_application_request.xsd +107 -0
- data/lib/sepa/xml_schemas/danske_pki.xsd +334 -0
- data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-secext-1.0.xsd +195 -0
- data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-utility-1.0.xsd +108 -0
- data/lib/sepa/xml_schemas/soap.xsd +126 -0
- data/lib/sepa/xml_schemas/wsdl.xml +310 -0
- data/lib/sepa/xml_schemas/xml.xsd +287 -0
- data/lib/sepa/xml_schemas/xmldsig-core-schema.xsd +318 -0
- data/lib/sepa/xml_templates/application_request/create_certificate.xml +10 -0
- data/lib/sepa/xml_templates/application_request/danske_get_bank_certificate.xml +10 -0
- data/lib/sepa/xml_templates/application_request/download_file.xml +32 -0
- data/lib/sepa/xml_templates/application_request/download_file_list.xml +29 -0
- data/lib/sepa/xml_templates/application_request/get_certificate.xml +10 -0
- data/lib/sepa/xml_templates/application_request/get_user_info.xml +26 -0
- data/lib/sepa/xml_templates/application_request/upload_file.xml +29 -0
- data/lib/sepa/xml_templates/soap/create_certificate.xml +15 -0
- data/lib/sepa/xml_templates/soap/danske_get_bank_certificate.xml +14 -0
- data/lib/sepa/xml_templates/soap/download_file.xml +16 -0
- data/lib/sepa/xml_templates/soap/download_file_list.xml +16 -0
- data/lib/sepa/xml_templates/soap/get_certificate.xml +13 -0
- data/lib/sepa/xml_templates/soap/get_user_info.xml +16 -0
- data/lib/sepa/xml_templates/soap/header.xml +37 -0
- data/lib/sepa/xml_templates/soap/upload_file.xml +16 -0
- data/lib/sepa.rb +21 -0
- data/lib/sepa_client_testing_mika.rb +32 -0
- data/lib/sepa_client_testing_tiere.rb +80 -0
- data/sepa.gemspec +29 -0
- data/test/sepa/application_request_test.rb +423 -0
- data/test/sepa/application_response_test.rb +238 -0
- data/test/sepa/cert_application_request_test.rb +99 -0
- data/test/sepa/client_test.rb +425 -0
- data/test/sepa/danske_test_keys/danskeroot.pem +25 -0
- data/test/sepa/danske_test_keys/encryption_pkcs.csr +0 -0
- data/test/sepa/danske_test_keys/signing_key.pem +27 -0
- data/test/sepa/danske_test_keys/signing_pkcs.csr +0 -0
- data/test/sepa/nordea_cert_request_soap_builder_test.rb +112 -0
- data/test/sepa/nordea_generic_soap_builder_test.rb +427 -0
- data/test/sepa/nordea_test_keys/nordea.crt +27 -0
- data/test/sepa/nordea_test_keys/nordea.key +19 -0
- data/test/sepa/nordea_test_keys/root_cert.cer +0 -0
- data/test/sepa/nordea_test_keys/testcert.csr +0 -0
- data/test/sepa/response_test.rb +269 -0
- data/test/sepa/sepa_test.rb +20 -0
- data/test/sepa/test_files/invalid.wsdl +1 -0
- data/test/sepa/test_files/test_responses/df.xml +20 -0
- data/test/sepa/test_files/test_responses/dfl.xml +20 -0
- data/test/sepa/test_files/test_responses/gui.xml +20 -0
- data/test/sepa/test_files/test_responses/uf.xml +20 -0
- data/test/sepa/user_file_type_test.rb +21 -0
- data/test/sepa/xml_parser_test.rb +73 -0
- data/test/test_helper.rb +9 -0
- 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
|