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.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +33 -0
- data/LICENSE +20 -0
- data/README.md +237 -0
- data/ige_isb_api.gemspec +29 -0
- data/lib/ige_isb_api.rb +49 -0
- data/lib/ige_isb_api/api.rb +251 -0
- data/lib/ige_isb_api/bonus.rb +249 -0
- data/lib/ige_isb_api/bonus_api.rb +125 -0
- data/lib/ige_isb_api/callback.rb +83 -0
- data/lib/ige_isb_api/constants.rb +284 -0
- data/lib/ige_isb_api/games.rb +433 -0
- data/lib/ige_isb_api/request.rb +164 -0
- data/lib/ige_isb_api/user_api.rb +251 -0
- data/lib/ige_isb_api/validation.rb +130 -0
- data/lib/ige_isb_api/version.rb +6 -0
- metadata +130 -0
@@ -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
|