ige_isb_api 1.0.0

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.
@@ -0,0 +1,164 @@
1
+ #!/user/bin/env ruby
2
+ #coding: utf-8
3
+
4
+ require "net/http"
5
+ require "uri"
6
+ require "ige_isb_api"
7
+ require "ige_isb_api/constants"
8
+ require "ige_isb_api/validation"
9
+
10
+ module IGE_ISB_API
11
+ class Request
12
+ attr_accessor :params, :request
13
+
14
+ DEFAULT_PARAMS = {
15
+ 'secretkey' => IGE_ISB_API::Constants::SECRET_KEY
16
+ }
17
+
18
+ COMMON_FIELDS = {
19
+ 'command' => {:required => true, :type => 'string', :length => 32},
20
+ 'idrequest' => {:required => true, :type => 'string', :length => 32},
21
+ 'secretkey' => {:required => true, :type => 'string', :length => 128},
22
+ 'username' => {:required => true, :type => 'username', :length => 32},
23
+ 'password' => {:required => true, :type => 'password', :length => 32}, # this differs from the docs but testing shows it's true.
24
+ 'txid' => {:required => true, :type => 'int'}
25
+ }
26
+
27
+ COMMANDS = {
28
+ 'registration' => {
29
+ 'email' => {:required => true, :type => 'email', :length => 140},
30
+ 'name' => {:required => true, :type => 'name', :length => 140},
31
+ 'firstname' => {:required => true, :type => 'name', :length => 140},
32
+ 'zip' => {:required => true, :type => 'string', :length => 10},
33
+ 'city' => {:required => true, :type => 'string', :length => 140},
34
+ 'phone' => {:required => true, :type => 'phone', :length => 32},
35
+ 'dob' => {:required => true, :type => 'datestring', :length => 10},
36
+ 'country' => {:required => true, :type => 'country'},
37
+ 'ip' => {:required => true, :type => 'ip4', :length => 32},
38
+ 'cur' => {:required => true, :type => 'currency_code', :length => 3},
39
+ 'status' => {:required => true, :type => 'int', values: [0, 1, 2]},
40
+ 'carte' => {:required => true, :type => 'string', :length => 32},
41
+ 'lang' => {:required => true, :type => 'string', :length => 2},
42
+ 'gender' => {:required => true, :type => 'int', values: [0, 1]},
43
+ 'idaffiliation' => {:required => true, :type => 'int'}
44
+ },
45
+ 'login' => {
46
+ 'carte' => {:required => true, :type => 'string', :length => 32}
47
+ },
48
+ 'deposit' => {
49
+ 'amount' => {:required => true, :type => 'int'},
50
+ 'reference' => {:required => true, :type => 'string', :length => 32},
51
+ 'cur' => {:required => true, :type => 'string', :length => 3},
52
+ 'wallet' => {:required => true, :type => 'string', :length => 32}
53
+ },
54
+ 'withdrawal' => {
55
+ 'amount' => {:required => true, :type => 'int'},
56
+ 'reference' => {:required => true, :type => 'string', :length => 32},
57
+ 'cur' => {:required => true, :type => 'currency_code', :length => 3},
58
+ 'wallet' => {:required => true, :type => 'string', :length => 32}
59
+ },
60
+ 'limits' => {
61
+ 'limitationtype' => {:required => true, :type => 'limit'},
62
+ 'amount' => {:required => true, :type => 'int'},
63
+ 'frequency' => {:required => true, :type => 'timespan'},
64
+ 'until' => {:required => true, :type => 'string', :length => 32}
65
+ },
66
+ 'userstatus' => {
67
+ 'flag' => {:required => true, :type => 'int'}
68
+ },
69
+ 'pass' => {
70
+ 'newpassword' => {:required => true, :type => 'string', :length => 32}
71
+ },
72
+ 'get_vip_points' => {
73
+ # nothing special
74
+ },
75
+ 'save_friend_email' => {
76
+ 'invitedname' => {:required => true, :type => 'string', :length => 32},
77
+ 'invitedemail' => {:required => true, :type => 'string', :length => 140}
78
+ }
79
+ }
80
+
81
+ def initialize(params = {})
82
+ self.params = self.class::DEFAULT_PARAMS.merge(self.convert_symbols_to_strings(params))
83
+ self.validate_parameters
84
+ # a bunch of stuff
85
+
86
+ self.construct_request
87
+ end
88
+
89
+ def send
90
+ uri = URI.parse(IGE_ISB_API::Constants::API_SERVER)
91
+ http = Net::HTTP.new(uri.host, uri.port)
92
+ # see http://www.rubyinside.com/nethttp-cheat-sheet-2940.html
93
+ # http.use_ssl = true
94
+ # http.cert = OpenSSL::X509::Certificate.new(pem)
95
+ # http.key = OpenSSL::PKey::RSA.new(pem)
96
+ # http.verify_mode = OpenSSL::SSL::VERIFY_PEER
97
+ return http.request(self.request)
98
+ end
99
+
100
+ protected
101
+
102
+ def convert_symbols_to_strings(a_hash = {})
103
+ return {} if a_hash.empty?
104
+ result = {}
105
+ a_hash.each {|key, value| result[key.to_s] = value }
106
+ return result
107
+ end
108
+
109
+ def validate_parameters
110
+ command = params['command']
111
+ raise ValidationException, "No command in params #{params.inspect}." if command.nil? || command.empty?
112
+ comfields = self.class::COMMANDS[command]
113
+ raise ValidationException, "Invalid command #{command}." if comfields.nil?
114
+ fields = self.class::COMMON_FIELDS.merge(comfields)
115
+ self.validate_fields(fields)
116
+ self.validate_no_extra_fields(fields)
117
+ end
118
+
119
+ def validate_fields(against)
120
+ against.each do |name, meta|
121
+ required = (meta[:required] === true)
122
+ # Check that all required parameters are present
123
+ if required && !self.params.keys.include?(name)
124
+ raise ValidationException, "Parameter #{name} is required, but missing from #{self.params.keys}"
125
+ end
126
+ if self.params.keys.include? name
127
+ p = self.params[name]
128
+ if p != nil
129
+ case meta[:type]
130
+ when 'timestamp'
131
+ self.params[name] = p = p.to_time.utc.to_i if p.is_a? Date
132
+ self.params[name] = p = p.utc.to_i if p.is_a?(Time)
133
+ self.params[name] = p = p.to_i if p.is_a?(String)
134
+ when 'currency'
135
+ p = p.to_f if p.is_a? String
136
+ if (p.is_a?(Float) || p.is_a?(Integer)) && p > 0
137
+ self.params[name] = p = "%.2f" % p
138
+ end
139
+ end
140
+ opts = {}
141
+ opts[:length] = meta[:length] if meta[:length]
142
+ opts[:values] = meta[:values] if meta[:values]
143
+ IGE_ISB_API::Validation.test name, self.params[name], meta[:type], opts
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ def validate_no_extra_fields(against)
150
+ allowed_fields = against.keys
151
+ self.params.each do |key, value|
152
+ raise InternalException, "Field #{key} is not supported" if !allowed_fields.include?(key)
153
+ end
154
+ end
155
+
156
+ def construct_request
157
+ uri = URI.parse(IGE_ISB_API::Constants::API_SERVER)
158
+ # http = Net::HTTP.new(uri.host, uri.port)
159
+ self.request = Net::HTTP::Post.new(uri)
160
+ self.request.set_form_data(self.params)
161
+ end
162
+
163
+ end
164
+ end
@@ -0,0 +1,251 @@
1
+ #!/user/bin/env ruby
2
+ #coding: utf-8
3
+
4
+ module IGE_ISB_API
5
+ class UserAPI
6
+
7
+ # the following options *must* be passed in.
8
+ # username: "some_username specific to iSoftBet",
9
+ # password: "should be specific to iSoftBet",
10
+ # The following options may be passed in and are presented here with their defaults.
11
+ # cur: IGE_ISB_API::Constants::DEFAULT_CURRENCY_CODE,
12
+ # carte: IGE_ISB_API::Constants::CASINO,
13
+ # lang: IGE_ISB_API::Constants::DEFAULT_LANGUAGE,
14
+ def initialize(player_status = IGE_ISB_API::Constants::TEST, opts = {})
15
+ raise ArgumentError, "Missing options." if opts.empty?
16
+ @options = {
17
+ cur: IGE_ISB_API::Constants::DEFAULT_CURRENCY_CODE,
18
+ carte: IGE_ISB_API::Constants::CASINO,
19
+ lang: IGE_ISB_API::Constants::DEFAULT_LANGUAGE,
20
+ status: player_status
21
+ }.merge(opts)
22
+ end
23
+
24
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
25
+ # Additionally each transaction must include a unique transaction ID.
26
+ # the following options *must* be passed in.
27
+ # email: "the user's email address",
28
+ # name: "the user's surname",
29
+ # firstname: "the user's first name",,
30
+ # zip: "the user's postcode",
31
+ # city: "the user's city",
32
+ # phone: "the user's phone number",
33
+ # dob: "in 2011-11-21 format",
34
+ # country: "the ISO country code for the user",
35
+ # ip: request.ip
36
+ #
37
+ # The following may be passed in and are presented here with their defaults.
38
+ # cur: IGE_ISB_API::Constants::DEFAULT_CURRENCY_CODE,
39
+ # status: IGE_ISB_API::Constants::TEST,
40
+ # carte: IGE_ISB_API::Constants::CASINO,
41
+ # lang: 'en',
42
+ # gender: IGE_ISB_API::Constants::MALE,
43
+ def register(label = '', txid = 0, opts = {})
44
+ validate_params!(label, txid)
45
+ raise ArgumentError, "Missing options." if opts.empty?
46
+ @params = { idrequest: label,
47
+ username: @options[:username],
48
+ password: @options[:password],
49
+ status: @options[:status],
50
+ cur: @options[:cur],
51
+ lang: @options[:lang],
52
+ carte: @options[:carte],
53
+ gender: IGE_ISB_API::Constants::MALE,
54
+ txid: txid}.merge(opts).merge({ command: 'registration', idaffiliation: IGE_ISB_API::Constants::LICENSEE_ID })
55
+ request = IGE_ISB_API.request(@params)
56
+ resp = request.send
57
+ response = JSON.parse(resp.body)
58
+ return response
59
+ end
60
+
61
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
62
+ # Additionally each transaction must include a unique transaction ID.
63
+ # The following may be passed in and is presented here with its default.
64
+ # carte: defaults to IGE_ISB_API::Constants::CASINO can can be overridden if user is logging in from
65
+ # a different casino under the control of the same licensee.
66
+ def login(label = '', txid = 0, opts = {})
67
+ validate_params!(label, txid)
68
+ @params = { idrequest: label,
69
+ username: @options[:username],
70
+ password: @options[:password],
71
+ carte: @options[:carte],
72
+ txid: txid}.merge(opts).merge({ command: 'login' })
73
+ request = IGE_ISB_API.request(@params)
74
+ resp = request.send
75
+ response = JSON.parse(resp.body)
76
+ return response
77
+ end
78
+
79
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
80
+ # Additionally each transaction must include a unique transaction ID.
81
+ # the following options *must* be passed in.
82
+ # wallet: "the name of the payment processor being used",
83
+ # amount: a positive floating point number,
84
+ # reference: "for logging purposes",
85
+ #
86
+ # The following may be passed in and are presented here with their defaults.
87
+ # cur: defaults to IGE_ISB_API::Constants::DEFAULT_CURRENCY_CODE
88
+ def deposit(label = '', txid = 0, opts = {})
89
+ validate_params!(label, txid)
90
+ raise ArgumentError, "Missing options." if opts.empty?
91
+ @params = { idrequest: label,
92
+ username: @options[:username],
93
+ password: @options[:password],
94
+ cur: @options[:cur],
95
+ txid: txid}.merge(opts).merge({ command: 'deposit' })
96
+ reference = "#{@params[:wallet]}:#{@params[:reference]}#{@params[:cur]}"
97
+ @params.merge!(reference: reference)
98
+ request = IGE_ISB_API.request(@params)
99
+ resp = request.send
100
+ response = JSON.parse(resp.body)
101
+ return response
102
+ end
103
+
104
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
105
+ # Additionally each transaction must include a unique transaction ID.
106
+ # the following options *must* be passed in.
107
+ # wallet: "the name of the payment processor being used",
108
+ # amount: a positive floating point number,
109
+ # reference: "for logging purposes",
110
+ #
111
+ # The following may be passed in and are presented here with their defaults.
112
+ # cur: defaults to IGE_ISB_API::Constants::DEFAULT_CURRENCY_CODE
113
+ def withdrawal(label = '', txid = 0, opts = {})
114
+ validate_params!(label, txid)
115
+ raise ArgumentError, "Missing options." if opts.empty?
116
+ @params = { idrequest: label,
117
+ username: @options[:username],
118
+ password: @options[:password],
119
+ cur: @options[:cur],
120
+ txid: txid}.merge(opts).merge({ command: 'withdrawal' })
121
+ reference = "#{@params[:reference]}#{@params[:cur]}"
122
+ @params.merge!(reference: reference)
123
+ request = IGE_ISB_API.request(@params)
124
+ resp = request.send
125
+ response = JSON.parse(resp.body)
126
+ return response
127
+ end
128
+
129
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
130
+ # Additionally each transaction must include a unique transaction ID.
131
+ # the following options *must* be passed in.
132
+ # limitationtype: 'DEPOSIT', 'DEPOSIT_EXTRA', 'BET', 'LOSS', 'TIME', 'EXCLUSION'
133
+ # amount: a positive floating point number,
134
+ # frequency: "WEEKLY", DAILY, MONTHLY, 1..n days - for exclusion
135
+ # until: "YYYY-MM-DD" or -1 for unlimited.
136
+ #
137
+ # The following may be passed in and are presented here with their defaults.
138
+ # cur: defaults to IGE_ISB_API::Constants::DEFAULT_CURRENCY_CODE
139
+ def limits(label = '', txid = 0, opts = {})
140
+ validate_params!(label, txid)
141
+ raise ArgumentError, "Missing options." if opts.empty?
142
+ @params = { idrequest: label,
143
+ username: @options[:username],
144
+ password: @options[:password],
145
+ txid: txid}.merge(opts).merge({ command: 'limits' })
146
+ request = IGE_ISB_API.request(@params)
147
+ resp = request.send
148
+ response = JSON.parse(resp.body)
149
+ return response
150
+ end
151
+
152
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
153
+ # Additionally each transaction must include a unique transaction ID.
154
+ def deactivate(label = '', txid = 0)
155
+ validate_params!(label, txid)
156
+ @params = { idrequest: label,
157
+ username: @options[:username],
158
+ password: @options[:password],
159
+ txid: txid}.merge({ command: 'userstatus', flag: IGE_ISB_API::Constants::USER_INACTIVE })
160
+ request = IGE_ISB_API.request(@params)
161
+ resp = request.send
162
+ response = JSON.parse(resp.body)
163
+ return response
164
+ end
165
+
166
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
167
+ # Additionally each transaction must include a unique transaction ID.
168
+ def activate(label = '', txid = 0)
169
+ validate_params!(label, txid)
170
+ @params = { idrequest: label,
171
+ username: @options[:username],
172
+ password: @options[:password],
173
+ txid: txid}.merge({ command: 'userstatus', flag: IGE_ISB_API::Constants::USER_ACTIVE })
174
+ request = IGE_ISB_API.request(@params)
175
+ resp = request.send
176
+ response = JSON.parse(resp.body)
177
+ return response
178
+ end
179
+
180
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
181
+ # Additionally each transaction must include a unique transaction ID.
182
+ def ban(label = '', txid = 0)
183
+ validate_params!(label, txid)
184
+ @params = { idrequest: label,
185
+ username: @options[:username],
186
+ password: @options[:password],
187
+ txid: txid}.merge({ command: 'userstatus', flag: IGE_ISB_API::Constants::USER_BANNED })
188
+ request = IGE_ISB_API.request(@params)
189
+ resp = request.send
190
+ response = JSON.parse(resp.body)
191
+ return response
192
+ end
193
+
194
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
195
+ # Additionally each transaction must include a unique transaction ID.
196
+ # the following option *must* be passed in.
197
+ # newpassword: 'some new password',
198
+ def change_password(label = '', txid = 0, opts = {})
199
+ validate_params!(label, txid)
200
+ raise ArgumentError, "Missing options." if opts.empty?
201
+ @params = { idrequest: label,
202
+ username: @options[:username],
203
+ password: @options[:password],
204
+ txid: txid}.merge(opts).merge({ command: 'pass'})
205
+ request = IGE_ISB_API.request(@params)
206
+ resp = request.send
207
+ response = JSON.parse(resp.body)
208
+ return response
209
+ end
210
+
211
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
212
+ # Additionally each transaction must include a unique transaction ID.
213
+ def get_vip_points(label = '', txid = 0)
214
+ validate_params!(label, txid)
215
+ @params = { idrequest: label,
216
+ username: @options[:username],
217
+ password: @options[:password],
218
+ txid: txid}.merge({ command: 'get_vip_points' })
219
+ request = IGE_ISB_API.request(@params)
220
+ resp = request.send
221
+ response = JSON.parse(resp.body)
222
+ return response
223
+ end
224
+
225
+ # Each command has a label which is used by the casino to tag a group of interactions with ISB
226
+ # Additionally each transaction must include a unique transaction ID.
227
+ # the following options *must* be passed in.
228
+ # invitedname: 'some new password',
229
+ # invitedemail: 'some new password',
230
+ def save_friend_email(label = '', txid = 0, opts = {})
231
+ validate_params!(label, txid)
232
+ raise ArgumentError, "Missing options." if opts.empty?
233
+ @params = { idrequest: label,
234
+ username: @options[:username],
235
+ password: @options[:password],
236
+ txid: txid}.merge(opts).merge({ command: 'save_friend_email'})
237
+ request = IGE_ISB_API.request(@params)
238
+ resp = request.send
239
+ response = JSON.parse(resp.body)
240
+ return response
241
+ end
242
+
243
+ private
244
+
245
+ def validate_params!(label, txid)
246
+ raise ArgumentError, "Missing a valid label." if label.empty?
247
+ raise ArgumentError, "Missing a valid transaction ID." if txid <= 0
248
+ end
249
+
250
+ end
251
+ end
@@ -0,0 +1,130 @@
1
+ #!/user/bin/env ruby
2
+ #coding: utf-8
3
+
4
+ require 'ige_isb_api'
5
+ require 'ige_isb_api/constants'
6
+
7
+ module IGE_ISB_API
8
+ class Validation
9
+
10
+ def self.is_valid_username?(a_username)
11
+ # Username must be alphanumeric
12
+ return false if a_username.size > 32
13
+ return !a_username.match(/^[[:alpha:]|[0-9]|\-_]+$/).nil?
14
+ end
15
+
16
+ def self.is_valid_password?(a_password)
17
+ # Password must be over 6 and less than 20 characters long; Password must be alphanumeric
18
+ return false unless a_password.size.between?(6,20)
19
+ return !a_password.match(/^[[:alpha:]|[0-9]]+$/).nil?
20
+ end
21
+
22
+ def self.is_valid_email?(an_email)
23
+ # see http://stackoverflow.com/questions/703060/valid-email-address-regular-expression
24
+ return false if an_email.empty?
25
+ email_regex = /(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*))*)?;\s*)/
26
+ return !an_email.match(email_regex).nil?
27
+ end
28
+
29
+ def self.is_valid_name?(a_name)
30
+ "0123456789!@#$%^&*()[]\\/+=?<>~;:{}".split('').each do |ch|
31
+ return false if a_name.include?(ch)
32
+ end
33
+ return true
34
+ end
35
+
36
+ def self.is_valid_phonenumber?(a_phonenumber)
37
+ # phone can start with +
38
+ # TODO: Awaiting feedback from ISB
39
+ numb_regex = /^\+?[0-9\(\s\)-]{5,21}$/
40
+ return !a_phonenumber.match(numb_regex).nil?
41
+ end
42
+
43
+ def self.is_valid_ip4?(an_ip)
44
+ # valid IP4 address
45
+ vip = an_ip.match /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/
46
+ return false if vip.nil?
47
+ return false unless $1.to_i.between?(0,255) && $2.to_i.between?(0,255) && $3.to_i.between?(0,255)
48
+ return true
49
+ end
50
+
51
+ def self.is_valid_datestring?(a_datestring)
52
+ dm = a_datestring.match /^((19|20)[0-9][0-9])-([0-9]{2})-([0-9]{2})\.([0-9]{2}):([0-9]{2}):([0-9]{2})$/
53
+ if dm.nil?
54
+ dm = a_datestring.match /^((19|20)[0-9][0-9])-([0-9]{2})-([0-9]{2})$/
55
+ return false if dm.nil?
56
+ else
57
+ return false unless $5.to_i.between?(0,23)
58
+ return false unless $6.to_i.between?(0,59)
59
+ return false unless $7.to_i.between?(0,59)
60
+ end
61
+ return false unless $1.to_i.between?(1900,2099)
62
+ return false unless $3.to_i.between?(1,12)
63
+ return false unless $4.to_i.between?(1,31)
64
+ return false if [9, 4, 6, 11].include?($3.to_i) && !$4.to_i.between?(1,30)
65
+ return false if $3.to_i == 2 && $1.to_i % 4 == 0 && !$4.to_i.between?(1,29) # leap year
66
+ return false if $3.to_i == 2 && !$4.to_i.between?(1,28) # non leap year
67
+ return true
68
+ end
69
+
70
+ def self.is_valid_currency?(an_amount)
71
+ vc = an_amount.match /^[1-9][0-9]*\.[0-9][0-9]$/
72
+ return !vc.nil?
73
+ end
74
+
75
+ def self.test(a_fieldname, a_value, a_type, opts = {})
76
+ correct_type = true
77
+ begin
78
+ case a_type
79
+ when 'username'
80
+ correct_type = a_value.is_a?(String) && is_valid_username?(a_value)
81
+ when 'password'
82
+ correct_type = a_value.is_a?(String) && is_valid_password?(a_value)
83
+ when 'boolstring'
84
+ correct_type = a_value.is_a?(String) && ['True', 'False'].include?(a_value)
85
+ when 'country'
86
+ correct_type = a_value.is_a?(String) && !IGE_ISB_API::Constants::ALLOWED_COUNTRY_CODES[a_value.to_sym].nil?
87
+ when 'limit'
88
+ correct_type = a_value.is_a?(String) && IGE_ISB_API::Constants::ALLOWED_LIMITATIONS.include?(a_value)
89
+ when 'timespan'
90
+ correct_type = a_value.is_a?(String) && IGE_ISB_API::Constants::ALLOWED_FREQUENCIES.include?(a_value)
91
+ when 'string'
92
+ correct_type = a_value.is_a? String
93
+ raise ValidationException, sprintf("Value '%s' in field '%s' is too long.", a_value, a_fieldname) if opts[:length] && a_value.size > opts[:length]
94
+ raise ValidationException, "#{a_value} is invalid for #{a_fieldname}" if opts[:values] && !opts[:values].include?(a_value)
95
+ when 'currency_code'
96
+ correct_type = a_value.is_a?(String) && IGE_ISB_API::Constants::ALLOWED_CURRENCIES.include?(a_value)
97
+ when 'currency'
98
+ correct_type = is_valid_currency?(a_value)
99
+ when 'percent'
100
+ correct_type = a_value.is_a?(Float) || a_value.is_a?(Integer)
101
+ raise ValidationException, "#{a_fieldname} must be positive" if a_value < 0
102
+ when 'int'
103
+ correct_type = a_value.is_a? Integer
104
+ raise ValidationException, "#{a_fieldname} only allows positive integers" if a_value < 0
105
+ raise ValidationException, "#{a_value} is invalid for #{a_fieldname}" if opts[:values] && !opts[:values].include?(a_value)
106
+ when 'boolint'
107
+ correct_type = a_value.is_a?(Integer) && [0, 1].include?(a_value)
108
+ when 'datestring'
109
+ correct_type = a_value.is_a? String
110
+ raise ValidationException, "#{a_value} is not a valid date string." unless is_valid_datestring?(a_value)
111
+ when 'timestamp'
112
+ correct_type = a_value.is_a? Integer
113
+ raise ValidationException, "#{a_value} is not a valid timestamp." unless a_value > 0
114
+ when 'phone'
115
+ correct_type = a_value.is_a?(String) && is_valid_phonenumber?(a_value)
116
+ when 'ip4'
117
+ correct_type = a_value.is_a?(String) && is_valid_ip4?(a_value)
118
+ when 'email'
119
+ correct_type = a_value.is_a?(String) && is_valid_email?(a_value)
120
+ end
121
+ rescue ArgumentError => ae
122
+ raise ValidationException, sprintf("Value '%s' in field '%s' is not of expected type '%s' Error: %s", a_value, a_fieldname, a_type, ae.message)
123
+ end
124
+
125
+ raise ValidationException, sprintf("Value '%s' in field '%s' is not of expected type '%s'", a_value, a_fieldname, a_type) unless correct_type
126
+
127
+ end
128
+
129
+ end
130
+ end