libgss 0.7.6 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +3 -3
- data/lib/libgss/action_request.rb +94 -3
- data/lib/libgss/async_action_request.rb +8 -6
- data/lib/libgss/network.rb +17 -8
- data/lib/libgss/version.rb +1 -1
- data/spec/factories/async_action.rb +2 -2
- data/spec/factories/{device_type.rb → client_release/device_type.rb} +0 -0
- data/spec/libgss/actions/dictionary_spec.rb +18 -15
- data/spec/libgss/actions/game_data_spec.rb +17 -16
- data/spec/libgss/actions/int_range_spec.rb +25 -22
- data/spec/libgss/actions/master_spec.rb +71 -67
- data/spec/libgss/actions/probability_spec.rb +23 -20
- data/spec/libgss/actions/schedule_spec.rb +28 -25
- data/spec/libgss/async_action_request_spec.rb +2 -1
- data/spec/libgss/response_signatrue_spec.rb +201 -0
- data/spec/spec_helper.rb +5 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 003ad5bfa2a5716b99d9f0d4198c07c3a3ff9e82
|
4
|
+
data.tar.gz: 4709750e7b9547e8a0fd707866bf89bf8e2b4a8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d5b51d3a75db29e2e3f9f0e3ab86c7487f692d668b02678e5bbadaebaec7c7ea1814d4326975ce24ab9f393197b1ed8f6baa6db8c86895284dbb52cb7cda8ae
|
7
|
+
data.tar.gz: b2db6f7782cd97f9979b0003c8cc17210de7a812cfe6780776275ccbf4bc110c441caa2d2a49e7a19ec6e75c8f627e745a8c8f9a7af69dc0cb853c67faaa7eb6
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
libgss (0.
|
4
|
+
libgss (0.8.0)
|
5
5
|
httpclient
|
6
6
|
json
|
7
7
|
oauth
|
@@ -21,7 +21,7 @@ GEM
|
|
21
21
|
diff-lcs (1.2.3)
|
22
22
|
factory_girl (4.2.0)
|
23
23
|
activesupport (>= 3.0.0)
|
24
|
-
fontana_client_support (0.
|
24
|
+
fontana_client_support (0.8.0)
|
25
25
|
httpclient (2.3.4.1)
|
26
26
|
i18n (0.6.5)
|
27
27
|
json (1.8.0)
|
@@ -33,7 +33,7 @@ GEM
|
|
33
33
|
origin (~> 1.0)
|
34
34
|
tzinfo (~> 0.3.29)
|
35
35
|
moped (1.5.1)
|
36
|
-
multi_json (1.
|
36
|
+
multi_json (1.8.0)
|
37
37
|
oauth (0.4.7)
|
38
38
|
origin (1.1.0)
|
39
39
|
rake (10.0.4)
|
@@ -11,6 +11,9 @@ module Libgss
|
|
11
11
|
class Error < StandardError
|
12
12
|
end
|
13
13
|
|
14
|
+
class SignatureError < Error
|
15
|
+
end
|
16
|
+
|
14
17
|
STATUS_PREPARING = 0
|
15
18
|
STATUS_SENDING = 1
|
16
19
|
STATUS_WAITING = 2
|
@@ -25,6 +28,8 @@ module Libgss
|
|
25
28
|
attr_reader :action_url, :req_headers
|
26
29
|
attr_reader :status, :outputs
|
27
30
|
|
31
|
+
attr_accessor :response_hook
|
32
|
+
|
28
33
|
# コンストラクタ
|
29
34
|
def initialize(network, action_url, req_headers)
|
30
35
|
@network = network
|
@@ -56,26 +61,104 @@ module Libgss
|
|
56
61
|
res = Libgss.with_retry("action_request") do
|
57
62
|
network.httpclient_for_action.post(action_url, {"inputs" => @actions.map(&:to_hash)}.to_json, req_headers)
|
58
63
|
end
|
59
|
-
|
64
|
+
response_hook.call(res) if response_hook # テストでレスポンスを改ざんを再現するために使います
|
65
|
+
r = process_response(res, :action_request)
|
60
66
|
@outputs = Outputs.new(r["outputs"])
|
61
67
|
callback.call(@outputs) if callback
|
62
68
|
@outputs
|
63
69
|
end
|
64
70
|
|
71
|
+
# レスポンスの処理を行います
|
65
72
|
def process_response(res, req_type)
|
66
73
|
case res.code.to_i
|
67
74
|
when 200..299 then # OK
|
68
75
|
else
|
69
76
|
raise Error, "failed to send #{req_type}: [#{res.code}] #{res.content}"
|
70
77
|
end
|
78
|
+
verify_signature(res) do |content|
|
79
|
+
begin
|
80
|
+
JSON.parse(content)
|
81
|
+
rescue JSON::ParserError => e
|
82
|
+
$stderr.puts("\e[31m[#{e.class}] #{e.message}\e[0m\n#{content}")
|
83
|
+
raise e
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
private :process_response
|
88
|
+
|
89
|
+
# シグネチャの検証を行います
|
90
|
+
def verify_signature(res, &block)
|
91
|
+
case network.api_version
|
92
|
+
when "1.0.0" then verify_signature_on_headers(res, &block)
|
93
|
+
when "1.1.0" then verify_signature_included_body(res, &block)
|
94
|
+
else
|
95
|
+
raise Error, "Unsupported API version: #{network.api_version}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# ヘッダから検証のための諸情報を取得します。
|
102
|
+
# キーの名前がbodyのJSONから取得する場合と微妙に違っているので注意してください。
|
103
|
+
def verify_signature_on_headers(res, &block)
|
104
|
+
content = res.content
|
105
|
+
attrs = {
|
106
|
+
content: content,
|
107
|
+
consumer_key: res.headers["Res-Sign-Consumer-Key"] || "",
|
108
|
+
nonce: res.headers["Res-Sign-Nonce"],
|
109
|
+
timestamp: res.headers["Res-Sign-Timestamp"],
|
110
|
+
}
|
111
|
+
verify_signature_by_oauth(res.headers["Res-Sign-Signature"], attrs, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
# bodyのJSONから検証のための諸情報を取得します。
|
115
|
+
# キーの名前がヘッダから取得する場合と微妙に違っているので注意してください。
|
116
|
+
def verify_signature_included_body(res, &block)
|
117
|
+
resp = nil
|
71
118
|
begin
|
72
|
-
|
119
|
+
resp = JSON.parse(res.content)
|
73
120
|
rescue JSON::ParserError => e
|
74
121
|
$stderr.puts("\e[31m[#{e.class}] #{e.message}\e[0m\n#{res.content}")
|
75
122
|
raise e
|
76
123
|
end
|
124
|
+
content = resp["body"]
|
125
|
+
attrs = {
|
126
|
+
content: content,
|
127
|
+
consumer_key: resp["res_sign_consumer_key"] || "",
|
128
|
+
nonce: resp["res_sign_nonce"],
|
129
|
+
timestamp: resp["res_sign_timestamp"],
|
130
|
+
}
|
131
|
+
verify_signature_by_oauth(resp["res_sign_signature"], attrs, &block)
|
77
132
|
end
|
78
|
-
|
133
|
+
|
134
|
+
def verify_signature_by_oauth(signature, attrs)
|
135
|
+
if network.skip_verifying_signature?
|
136
|
+
return yield(attrs[:content]) if block_given?
|
137
|
+
end
|
138
|
+
res_hash = {
|
139
|
+
"uri" => "",
|
140
|
+
"method" => "",
|
141
|
+
"parameters" => {
|
142
|
+
"body" => attrs[:content],
|
143
|
+
"oauth_consumer_key" => attrs[:consumer_key],
|
144
|
+
"oauth_token" => network.auth_token,
|
145
|
+
"oauth_signature_method" => "HMAC-SHA1",
|
146
|
+
"oauth_nonce" => attrs[:nonce],
|
147
|
+
"oauth_timestamp" => attrs[:timestamp]
|
148
|
+
}
|
149
|
+
}
|
150
|
+
s = OAuth::Signature.build(res_hash){ [ network.signature_key, network.consumer_secret] }
|
151
|
+
# puts "res_hash: " << res_hash.inspect
|
152
|
+
# puts "signature_key: " << network.signature_key.inspect
|
153
|
+
# puts "consumer_secret: " << network.consumer_secret.inspect
|
154
|
+
# puts "signature_base_string: " << s.signature_base_string
|
155
|
+
unless signature == s.signature
|
156
|
+
raise SignatureError, "invalid signature or something"
|
157
|
+
end
|
158
|
+
return yield(attrs[:content]) if block_given?
|
159
|
+
end
|
160
|
+
|
161
|
+
public
|
79
162
|
|
80
163
|
# 条件に該当するデータを取得
|
81
164
|
# @param [String] name 対象となるコレクション名
|
@@ -88,6 +171,7 @@ module Libgss
|
|
88
171
|
args[:order] = order if order
|
89
172
|
add_action(args)
|
90
173
|
end
|
174
|
+
alias_method :all, :find_all
|
91
175
|
|
92
176
|
# ページネーション付きで条件に該当するデータを取得
|
93
177
|
# @param [String] name 対象となるコレクション名
|
@@ -124,6 +208,7 @@ module Libgss
|
|
124
208
|
args[:order] = order if order
|
125
209
|
add_action(args)
|
126
210
|
end
|
211
|
+
alias_method :first, :find_first
|
127
212
|
|
128
213
|
# 辞書テーブルからinputに対応するoutputの値を返します。
|
129
214
|
# @param [String] name 対象となる辞書のコレクション名
|
@@ -135,6 +220,7 @@ module Libgss
|
|
135
220
|
args[:conditions] = conditions if conditions
|
136
221
|
add_action(args)
|
137
222
|
end
|
223
|
+
alias_method :get_dictionary, :get_by_dictionary
|
138
224
|
|
139
225
|
# 期間テーブルからinputに対応するoutputの値を返します。
|
140
226
|
# @param [String] name 対象となる機関テーブルのコレクション名
|
@@ -146,6 +232,7 @@ module Libgss
|
|
146
232
|
args[:conditions] = conditions if conditions
|
147
233
|
add_action(args)
|
148
234
|
end
|
235
|
+
alias_method :get_schedule, :get_by_schedule
|
149
236
|
|
150
237
|
# 整数範囲テーブルからinputに対応するoutputの値を返します。
|
151
238
|
# @param [String] name 対象となる整数範囲テーブルのコレクション名
|
@@ -157,6 +244,7 @@ module Libgss
|
|
157
244
|
args[:conditions] = conditions if conditions
|
158
245
|
add_action(args)
|
159
246
|
end
|
247
|
+
alias_method :get_int_range, :get_by_int_range
|
160
248
|
|
161
249
|
# 確率テーブルからinputに対応するoutputの値を返します。
|
162
250
|
# diceがあるのであまり使われないはず。
|
@@ -170,6 +258,7 @@ module Libgss
|
|
170
258
|
args[:conditions] = conditions if conditions
|
171
259
|
add_action(args)
|
172
260
|
end
|
261
|
+
alias_method :get_probability, :get_by_probability
|
173
262
|
|
174
263
|
# プレイヤーからplayer_idに対応するプレイヤーを返します
|
175
264
|
#
|
@@ -183,6 +272,7 @@ module Libgss
|
|
183
272
|
args[:player_id] = player_id.to_s if player_id
|
184
273
|
add_action(args)
|
185
274
|
end
|
275
|
+
alias_method :get_player, :get_by_player
|
186
276
|
|
187
277
|
# ゲームデータからplayer_idに対応するゲームデータを返します
|
188
278
|
#
|
@@ -196,6 +286,7 @@ module Libgss
|
|
196
286
|
args[:player_id] = player_id.to_s if player_id
|
197
287
|
add_action(args)
|
198
288
|
end
|
289
|
+
alias_method :get_game_data, :get_by_game_data
|
199
290
|
|
200
291
|
|
201
292
|
|
@@ -22,10 +22,11 @@ module Libgss
|
|
22
22
|
# アクション群を実行するために実際にHTTPリクエストを送信します。
|
23
23
|
def send_request
|
24
24
|
res = network.httpclient_for_action.post(action_url, {"inputs" => @actions.map(&:to_hash)}.to_json, req_headers)
|
25
|
-
|
26
|
-
|
27
|
-
@
|
28
|
-
outputs
|
25
|
+
response_hook.call(res) if response_hook # テストでレスポンスを改ざんを再現するために使います
|
26
|
+
r = process_response(res, :async_action_request)
|
27
|
+
@outputs = Outputs.new(r["outputs"])
|
28
|
+
@ids = @outputs.map{|output| output['id'] }
|
29
|
+
@outputs
|
29
30
|
end
|
30
31
|
|
31
32
|
def async_status(ids=nil)
|
@@ -34,8 +35,9 @@ module Libgss
|
|
34
35
|
raise Error, "failed to get response. please exec send_request before call." unless ids
|
35
36
|
|
36
37
|
res = network.httpclient_for_action.post(result_url, {'input_ids' => ids}.to_json, req_headers)
|
37
|
-
|
38
|
-
|
38
|
+
response_hook.call(res) if response_hook # テストでレスポンスを改ざんを再現するために使います
|
39
|
+
r = process_response(res, :aync_results_request)
|
40
|
+
@outputs = Outputs.new(r["outputs"]) # Outputsを使うことでidによるアクセスを可能に
|
39
41
|
end
|
40
42
|
alias :async_results :async_status
|
41
43
|
end
|
data/lib/libgss/network.rb
CHANGED
@@ -15,8 +15,6 @@ module Libgss
|
|
15
15
|
class Error < StandardError
|
16
16
|
end
|
17
17
|
|
18
|
-
API_VERSION = "1.0.0".freeze
|
19
|
-
|
20
18
|
attr_reader :base_url
|
21
19
|
attr_reader :ssl_base_url
|
22
20
|
attr_reader :ssl_disabled
|
@@ -39,6 +37,8 @@ module Libgss
|
|
39
37
|
attr_accessor :client_version
|
40
38
|
attr_accessor :device_type_cd
|
41
39
|
|
40
|
+
attr_accessor :skip_verifying_signature
|
41
|
+
|
42
42
|
PRODUCTION_HTTP_PORT = 80
|
43
43
|
PRODUCTION_HTTPS_PORT = 443
|
44
44
|
|
@@ -50,13 +50,15 @@ module Libgss
|
|
50
50
|
# @param [String] base_url_or_host 接続先の基準となるURLあるいはホスト名
|
51
51
|
# @param [Hash] options オプション
|
52
52
|
# @option options [String] :platform 接続先のGSSサーバの認証のプラットフォーム。デフォルトは"fontana"。
|
53
|
+
# @option options [String] :api_version APIのバージョン。デフォルトは "1.0.0"
|
53
54
|
# @option options [String] :player_id 接続に使用するプレイヤのID
|
54
55
|
# @option options [String] :consumer_secret GSSサーバとクライアントの間で行う署名の検証に使用される文字列。
|
55
56
|
# @option options [Boolean] :ignore_oauth_nonce OAuth認証時にoauth_nonceとoauth_timestampを使用しないかどうか。
|
56
57
|
# @option options [String] :oauth_nonce OAuth認証のoauth_nonceパラメータ
|
57
58
|
# @option options [Integer] :oauth_timestamp OAuth認証のoauth_timestampパラメータ
|
58
59
|
# @option options [Boolean] :ssl_disabled SSLを無効にするかどうか。
|
59
|
-
# @option options [Boolean] :ignore_signature_key
|
60
|
+
# @option options [Boolean] :ignore_signature_key シグネチャキーによる署名を無視するかどうか
|
61
|
+
# @option options [Boolean] :skip_verifying_signature レスポンスのシグネチャキーによる署名の検証をスキップするかどうか
|
60
62
|
# @option options [Integer] :device_type_cd GSS/fontanaに登録されたデバイス種別
|
61
63
|
# @option options [String] :client_version GSS/fontanaに登録されたクライアントリリースのバージョン
|
62
64
|
def initialize(base_url_or_host, options = {})
|
@@ -72,6 +74,7 @@ module Libgss
|
|
72
74
|
end
|
73
75
|
@ssl_base_url = @base_url if @ssl_disabled
|
74
76
|
@platform = options[:platform] || "fontana"
|
77
|
+
@api_version = options[:api_version] || "1.0.0"
|
75
78
|
@player_id = options[:player_id]
|
76
79
|
@player_info = options[:player_info] || {}
|
77
80
|
|
@@ -84,6 +87,8 @@ module Libgss
|
|
84
87
|
@device_type_cd = options[:device_type_cd]
|
85
88
|
@client_version = options[:client_version]
|
86
89
|
|
90
|
+
@skip_verifying_signature = options[:skip_verifying_signature]
|
91
|
+
|
87
92
|
@httpclient = HTTPClient.new
|
88
93
|
@httpclient.ssl_config.verify_mode = nil # 自己署名の証明書をOKにする
|
89
94
|
end
|
@@ -130,6 +135,11 @@ module Libgss
|
|
130
135
|
@ignore_signature_key
|
131
136
|
end
|
132
137
|
|
138
|
+
# @return [Boolean] コンストラクタに指定されたskip_verifying_signatureを返します
|
139
|
+
def skip_verifying_signature?
|
140
|
+
@skip_verifying_signature
|
141
|
+
end
|
142
|
+
|
133
143
|
# load_player_id メソッドをオーバーライドした場合に使用することを想定しています。
|
134
144
|
# それ以外の場合は使用しないでください。
|
135
145
|
def setup
|
@@ -204,7 +214,6 @@ module Libgss
|
|
204
214
|
HttpClientWithSignatureKey.new(@httpclient, self)
|
205
215
|
end
|
206
216
|
|
207
|
-
|
208
217
|
private
|
209
218
|
|
210
219
|
def req_headers
|
@@ -258,15 +267,15 @@ module Libgss
|
|
258
267
|
end
|
259
268
|
|
260
269
|
def action_url
|
261
|
-
@action_url ||= base_url + "/api/#{
|
270
|
+
@action_url ||= base_url + "/api/#{api_version}/actions.json?auth_token=#{auth_token}"
|
262
271
|
end
|
263
272
|
|
264
273
|
def async_action_url
|
265
|
-
@async_action_url ||= base_url + "/api/#{
|
274
|
+
@async_action_url ||= base_url + "/api/#{api_version}/async_actions.json?auth_token=#{auth_token}"
|
266
275
|
end
|
267
276
|
|
268
277
|
def async_result_url
|
269
|
-
@async_result_url ||= base_url + "/api/#{
|
278
|
+
@async_result_url ||= base_url + "/api/#{api_version}/async_results.json?auth_token=#{auth_token}"
|
270
279
|
end
|
271
280
|
|
272
281
|
def public_asset_url(asset_path)
|
@@ -275,7 +284,7 @@ module Libgss
|
|
275
284
|
|
276
285
|
def protected_asset_url(asset_path)
|
277
286
|
path = URI.encode(asset_path) # パラメータとして渡されるのでURLエンコードする必要がある
|
278
|
-
@action_url ||= base_url + "/api/#{
|
287
|
+
@action_url ||= base_url + "/api/#{api_version}/assets?path=#{path}&auth_token=#{auth_token}"
|
279
288
|
end
|
280
289
|
end
|
281
290
|
|
data/lib/libgss/version.rb
CHANGED
@@ -14,10 +14,10 @@ FactoryGirl.define do
|
|
14
14
|
|
15
15
|
factory :async_action02, class: AsyncAction do
|
16
16
|
player
|
17
|
-
action_id
|
17
|
+
action_id 2
|
18
18
|
request_url "http://localhost:3000/api/1.0.0/async_actions.json?auth_token=CzyWmCg3vjpxeYuHL8dr"
|
19
19
|
request({"id"=>2, "action"=>"server_time"})
|
20
|
-
response({"result"=>1379990870, "id"=>
|
20
|
+
response({"result"=>1379990870, "id"=>2})
|
21
21
|
attempts 0
|
22
22
|
end
|
23
23
|
|
File without changes
|
@@ -11,25 +11,28 @@ describe Libgss::ActionRequest do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
shared_examples_for "Libgss::ActionRequest#get_by_dictionary" do |input, output, conditions|
|
15
|
+
[:get_dictionary, :get_by_dictionary].each do |action|
|
16
|
+
describe "##{action}" do
|
17
|
+
it do
|
18
|
+
callback_called = false
|
19
|
+
request.send(action, "ArmorUpgrade1", input, conditions)
|
20
|
+
request.send_request do |outputs|
|
21
|
+
callback_called = true
|
22
|
+
outputs.length.should == 1
|
23
|
+
outputs.first["result"].should == output
|
24
|
+
end
|
25
|
+
callback_called.should == true
|
23
26
|
end
|
24
|
-
callback_called.should == true
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10001, 10002, nil
|
29
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10002, 10004, nil
|
30
|
-
|
31
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10001, nil, {"input$gt" => 10003}
|
32
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10002, nil, {"input$gt" => 10003}
|
33
30
|
end
|
34
31
|
|
32
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10001, 10002, nil
|
33
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10002, 10004, nil
|
34
|
+
|
35
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10001, nil, {"input$gt" => 10003}
|
36
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_dictionary", 10002, nil, {"input$gt" => 10003}
|
37
|
+
|
35
38
|
end
|
@@ -33,25 +33,26 @@ describe Libgss::ActionRequest do
|
|
33
33
|
"read_notifications"=>[]
|
34
34
|
}
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
[:get_game_data, :get_by_game_data].each do |action|
|
37
|
+
describe "##{action}" do
|
38
|
+
before do
|
39
|
+
request_fixture_load("01_basic")
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
42
|
+
it action do
|
43
|
+
callback_called = false
|
44
|
+
request.send(action)
|
45
|
+
request.send_request do |outputs|
|
46
|
+
callback_called = true
|
47
|
+
outputs.length.should == 1
|
48
|
+
game_data = outputs.first["result"]
|
49
|
+
# AppSeedで定義されているデータの確認
|
50
|
+
# game_data.select!{|k,v| expected_game_data_1000001.keys.include?(k) }
|
51
|
+
game_data.should == expected_game_data_1000001
|
52
|
+
end
|
53
|
+
callback_called.should == true
|
51
54
|
end
|
52
|
-
callback_called.should == true
|
53
55
|
end
|
54
|
-
|
55
56
|
end
|
56
57
|
|
57
58
|
describe "#update" do
|
@@ -11,32 +11,35 @@ describe Libgss::ActionRequest do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
shared_examples_for "Libgss::ActionRequest#get_by_int_range" do |input, output, conditions|
|
15
|
+
[:get_int_range, :get_by_int_range].each do |action|
|
16
|
+
describe "##{action}" do
|
17
|
+
it action do
|
18
|
+
callback_called = false
|
19
|
+
request.send(action, "RequiredExperience", input, conditions)
|
20
|
+
request.send_request do |outputs|
|
21
|
+
callback_called = true
|
22
|
+
outputs.length.should == 1
|
23
|
+
outputs.first["result"].should == output
|
24
|
+
end
|
25
|
+
callback_called.should == true
|
23
26
|
end
|
24
|
-
callback_called.should == true
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 0, 1, nil
|
29
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 9, 1, nil
|
30
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 10, 2, nil
|
31
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 24, 2, nil
|
32
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 25, 3, nil
|
33
|
-
|
34
|
-
cond = {"value$gte" => 10 }
|
35
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 0, nil, cond
|
36
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 9, nil, cond
|
37
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 10, nil, cond
|
38
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 24, nil, cond
|
39
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 25, nil, cond
|
40
30
|
end
|
41
31
|
|
32
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 0, 1, nil
|
33
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 9, 1, nil
|
34
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 10, 2, nil
|
35
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 24, 2, nil
|
36
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 25, 3, nil
|
37
|
+
|
38
|
+
cond = {"value$gte" => 10 }
|
39
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 0, nil, cond
|
40
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 9, nil, cond
|
41
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 10, nil, cond
|
42
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 24, nil, cond
|
43
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_int_range", 25, nil, cond
|
44
|
+
|
42
45
|
end
|
@@ -10,50 +10,52 @@ describe Libgss::ActionRequest do
|
|
10
10
|
network.new_action_request
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
13
|
+
[:all, :find_all].each do |action|
|
14
|
+
describe "##{action}" do
|
15
|
+
it "basic call" do
|
16
|
+
callback_called = false
|
17
|
+
request.send(action, "Item")
|
18
|
+
request.send_request do |outputs|
|
19
|
+
callback_called = true
|
20
|
+
outputs.length.should == 1
|
21
|
+
items = outputs.first["result"]
|
22
|
+
items.length.should == 12
|
23
|
+
items.each do |item|
|
24
|
+
item["item_cd"].should_not == nil
|
25
|
+
item["name"].should_not == nil
|
26
|
+
end
|
25
27
|
end
|
28
|
+
callback_called.should == true
|
26
29
|
end
|
27
|
-
callback_called.should == true
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
31
|
+
it "with conditions" do
|
32
|
+
callback_called = false
|
33
|
+
request.send(action, "Item", {"item_cd$gte" => 20005, "item_cd$lte" => 20008})
|
34
|
+
request.send_request do |outputs|
|
35
|
+
callback_called = true
|
36
|
+
outputs.length.should == 1
|
37
|
+
items = outputs.first["result"]
|
38
|
+
items.length.should == 4
|
39
|
+
items.each do |item|
|
40
|
+
item["item_cd"].should_not == nil
|
41
|
+
item["name"].should_not == nil
|
42
|
+
end
|
41
43
|
end
|
44
|
+
callback_called.should == true
|
42
45
|
end
|
43
|
-
callback_called.should == true
|
44
|
-
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
47
|
+
it "with order and conditions" do
|
48
|
+
callback_called = false
|
49
|
+
request.send(action, "Item", {"item_cd$gte" => 20005, "item_cd$lte" => 20008}, [["item_cd", "desc"]])
|
50
|
+
request.send_request do |outputs|
|
51
|
+
callback_called = true
|
52
|
+
outputs.length.should == 1
|
53
|
+
items = outputs.first["result"]
|
54
|
+
items.length.should == 4
|
55
|
+
items.map{|item| item["item_cd"]}.should == [20008, 20007, 20006, 20005]
|
56
|
+
end
|
57
|
+
callback_called.should == true
|
55
58
|
end
|
56
|
-
callback_called.should == true
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
@@ -96,41 +98,43 @@ describe Libgss::ActionRequest do
|
|
96
98
|
end
|
97
99
|
end
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
101
|
+
[:first, :find_first].each do |action|
|
102
|
+
describe "##{action}" do
|
103
|
+
it "basic call" do
|
104
|
+
callback_called = false
|
105
|
+
request.send(action, "Item")
|
106
|
+
request.send_request do |outputs|
|
107
|
+
callback_called = true
|
108
|
+
outputs.length.should == 1
|
109
|
+
item = outputs.first["result"]
|
110
|
+
item["item_cd"].should == 20001
|
111
|
+
end
|
112
|
+
callback_called.should == true
|
108
113
|
end
|
109
|
-
callback_called.should == true
|
110
|
-
end
|
111
114
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
115
|
+
it "with conditions" do
|
116
|
+
callback_called = false
|
117
|
+
request.send(action, "Item", {"item_cd$gte" => 20005, "item_cd$lte" => 20008})
|
118
|
+
request.send_request do |outputs|
|
119
|
+
callback_called = true
|
120
|
+
outputs.length.should == 1
|
121
|
+
item = outputs.first["result"]
|
122
|
+
item["item_cd"].should == 20005
|
123
|
+
end
|
124
|
+
callback_called.should == true
|
120
125
|
end
|
121
|
-
callback_called.should == true
|
122
|
-
end
|
123
126
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
127
|
+
it "with order and conditions" do
|
128
|
+
callback_called = false
|
129
|
+
request.send(action, "Item", {"item_cd$gte" => 20005, "item_cd$lte" => 20008}, [["item_cd", "desc"]])
|
130
|
+
request.send_request do |outputs|
|
131
|
+
callback_called = true
|
132
|
+
outputs.length.should == 1
|
133
|
+
item = outputs.first["result"]
|
134
|
+
item["item_cd"].should == 20008
|
135
|
+
end
|
136
|
+
callback_called.should == true
|
132
137
|
end
|
133
|
-
callback_called.should == true
|
134
138
|
end
|
135
139
|
end
|
136
140
|
|
@@ -10,33 +10,36 @@ describe Libgss::ActionRequest do
|
|
10
10
|
network.new_action_request
|
11
11
|
end
|
12
12
|
|
13
|
-
describe "#get_by_probability" do
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
14
|
+
shared_examples_for "Libgss::ActionRequest#get_by_probability" do |value, conditions, result|
|
15
|
+
[:get_probability, :get_by_probability].each do |action|
|
16
|
+
describe "##{action}" do
|
17
|
+
it "#{value.inspect} with #{conditions.inspect} returns #{result.inspect}" do
|
18
|
+
callback_called = false
|
19
|
+
request.send(action, "Composition1", value, conditions)
|
20
|
+
request.send_request do |outputs|
|
21
|
+
callback_called = true
|
22
|
+
outputs.length.should == 1
|
23
|
+
obj = outputs.first["result"]
|
24
|
+
# AppSeedで定義されているデータの確認
|
25
|
+
obj.should == result
|
26
|
+
end
|
27
|
+
callback_called.should == true
|
25
28
|
end
|
26
|
-
callback_called.should == true
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
|
31
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_probability", 20007, nil, 20
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_probability", 20007, {"element" => { "20002" => 1, "20006" => 2 } }, nil
|
34
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_probability", 10002, nil, 60
|
35
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_probability", 20007, nil, 20
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
context "with conditions" do
|
38
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_probability", 20007, {"element" => { "20002" => 1, "20006" => 1 } }, 20
|
39
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_probability", 20007, {"element" => { "20002" => 1, "20006" => 2 } }, nil
|
40
|
+
|
41
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_probability", {"20002" => 2}, {"element" => { "20002" => 1, "20006" => 1 } }, 80
|
42
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_probability", {"20002" => 2}, {"element" => { "20002" => 1, "20006" => 2 } }, nil
|
40
43
|
end
|
41
44
|
|
42
45
|
describe "#dice" do
|
@@ -11,35 +11,38 @@ describe Libgss::ActionRequest do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
shared_examples_for "Libgss::ActionRequest#get_by_schedule" do |input, output, conditions|
|
15
|
+
[:get_schedule, :get_by_schedule].each do |action|
|
16
|
+
describe "##{action}" do
|
17
|
+
it action do
|
18
|
+
callback_called = false
|
19
|
+
request.send(action, "ShopSchedule", input, conditions)
|
20
|
+
request.send_request do |outputs|
|
21
|
+
callback_called = true
|
22
|
+
outputs.length.should == 1
|
23
|
+
outputs.first["result"].should == output
|
24
|
+
end
|
25
|
+
callback_called.should == true
|
23
26
|
end
|
24
|
-
callback_called.should == true
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/09 00:00:00+09:00").to_i, "ShopMenu1", nil
|
29
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 11:59:59+09:00").to_i, "ShopMenu1", nil
|
30
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 12:00:00+09:00").to_i, "ShopMenu2", nil
|
31
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/15 12:00:00+09:00").to_i, "ShopMenu2", nil
|
32
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 12:59:59+09:00").to_i, "ShopMenu2", nil
|
33
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 13:00:00+09:00").to_i, "ShopMenu2", nil # 整数範囲テーブルと違って末尾にも含まれる
|
34
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 13:00:01+09:00").to_i, "ShopMenu1", nil
|
35
|
-
|
36
|
-
cond = {"value$ne" => "ShopMenu2" }
|
37
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/09 00:00:00+09:00").to_i, "ShopMenu1", cond
|
38
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 11:59:59+09:00").to_i, "ShopMenu1", cond
|
39
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 12:00:00+09:00").to_i, "ShopMenu1", cond
|
40
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/15 12:00:00+09:00").to_i, "ShopMenu1", cond
|
41
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 12:59:59+09:00").to_i, "ShopMenu1", cond
|
42
|
-
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 13:00:00+09:00").to_i, "ShopMenu1", cond
|
43
30
|
end
|
44
31
|
|
32
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/09 00:00:00+09:00").to_i, "ShopMenu1", nil
|
33
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 11:59:59+09:00").to_i, "ShopMenu1", nil
|
34
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 12:00:00+09:00").to_i, "ShopMenu2", nil
|
35
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/15 12:00:00+09:00").to_i, "ShopMenu2", nil
|
36
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 12:59:59+09:00").to_i, "ShopMenu2", nil
|
37
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 13:00:00+09:00").to_i, "ShopMenu2", nil # 整数範囲テーブルと違って末尾にも含まれる
|
38
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 13:00:01+09:00").to_i, "ShopMenu1", nil
|
39
|
+
|
40
|
+
cond = {"value$ne" => "ShopMenu2" }
|
41
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/09 00:00:00+09:00").to_i, "ShopMenu1", cond
|
42
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 11:59:59+09:00").to_i, "ShopMenu1", cond
|
43
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/10 12:00:00+09:00").to_i, "ShopMenu1", cond
|
44
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/15 12:00:00+09:00").to_i, "ShopMenu1", cond
|
45
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 12:59:59+09:00").to_i, "ShopMenu1", cond
|
46
|
+
it_should_behave_like "Libgss::ActionRequest#get_by_schedule", Time.parse("2012/07/20 13:00:00+09:00").to_i, "ShopMenu1", cond
|
47
|
+
|
45
48
|
end
|
@@ -72,6 +72,7 @@ describe Libgss::AsyncActionRequest do
|
|
72
72
|
describe "async_status(POST: async_results.json)" do
|
73
73
|
|
74
74
|
context "working async_action" do
|
75
|
+
|
75
76
|
before do
|
76
77
|
Player.delete_all
|
77
78
|
AsyncAction.delete_all
|
@@ -97,7 +98,7 @@ describe Libgss::AsyncActionRequest do
|
|
97
98
|
|
98
99
|
it do
|
99
100
|
r = network.new_async_action_request
|
100
|
-
r.async_status([
|
101
|
+
r.async_status([2]).to_a.should == [{"id" => 2, "result" => 1379990870}]
|
101
102
|
end
|
102
103
|
end
|
103
104
|
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'active_support/core_ext/numeric/time'
|
4
|
+
|
5
|
+
describe "response_signature" do
|
6
|
+
before do
|
7
|
+
request_fixture_load("01_basic")
|
8
|
+
end
|
9
|
+
shared_examples_for "action_request with response_signature" do |api_version|
|
10
|
+
before do
|
11
|
+
# 通信経路上で実際の時刻より過去の時刻を返すようにレスポンスを改ざんしていることを
|
12
|
+
# 想定して、レスポンスオブジェクトのcontentだけ内容を書き換えます。
|
13
|
+
@cheat = Proc.new do |res|
|
14
|
+
@cheated = res.content.dup
|
15
|
+
@cheated.sub!(/"result":(\d+)/){ "\"result\":%d" % ($1.to_i - 30.days) }
|
16
|
+
@cheated.sub!(/\\"result\\":(\d+)/){ "\\\"result\\\":%d" % ($1.to_i - 30.days) }
|
17
|
+
res.stub(:content).and_return(@cheated)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "valid" do
|
22
|
+
it do
|
23
|
+
req = @network.new_action_request
|
24
|
+
req.server_time
|
25
|
+
req.send_request
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "invalid response body" do
|
30
|
+
it "raise SignatureError" do
|
31
|
+
req = @network.new_action_request
|
32
|
+
req.server_time
|
33
|
+
req.response_hook = @cheat
|
34
|
+
expect{ req.send_request }.to raise_error(Libgss::ActionRequest::SignatureError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "with skip_verifying_signature" do
|
38
|
+
@network.skip_verifying_signature = true
|
39
|
+
req = @network.new_action_request
|
40
|
+
req.server_time
|
41
|
+
req.response_hook = @cheat
|
42
|
+
expect{ req.send_request }.to_not raise_error(Libgss::ActionRequest::SignatureError)
|
43
|
+
# 検証をスキップしているので、通信経路上で改ざんされたデータを取得できてしまう
|
44
|
+
req.outputs.to_a.should be_a(Array)
|
45
|
+
req.outputs.first.should be_a(Hash)
|
46
|
+
req.outputs.first["id"].should == 1
|
47
|
+
req.outputs.first["result"].should be_a(Integer)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "action_request" do
|
53
|
+
context "default" do
|
54
|
+
before{ @network = new_network.login! }
|
55
|
+
it_should_behave_like "action_request with response_signature"
|
56
|
+
end
|
57
|
+
|
58
|
+
context "1.0.0" do
|
59
|
+
before{ @network = new_network_with_options(api_version: "1.0.0").login! }
|
60
|
+
it_should_behave_like "action_request with response_signature"
|
61
|
+
end
|
62
|
+
|
63
|
+
context "1.1.0" do
|
64
|
+
before{ @network = new_network_with_options(api_version: "1.1.0").login! }
|
65
|
+
it_should_behave_like "action_request with response_signature"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
shared_examples_for "async_action_request with response_signature" do
|
71
|
+
context "valid" do
|
72
|
+
it do
|
73
|
+
req = @network.new_async_action_request
|
74
|
+
req.server_time
|
75
|
+
req.send_request
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "invalid response body" do
|
80
|
+
before do
|
81
|
+
# 通信経路上で実際の時刻より過去の時刻を返すようにレスポンスを改ざんしていることを
|
82
|
+
# 想定して、レスポンスオブジェクトのcontentだけ内容を書き換えます。
|
83
|
+
@cheat = Proc.new do |res|
|
84
|
+
@cheated = res.content.dup
|
85
|
+
@cheated.sub!(/"status":"executing"/){ "\"result\":%d" % (Time.now.to_i - 30.days) }
|
86
|
+
@cheated.sub!(/\\"status\\":\\"executing\\"/){ "\\\"result\\\":%d" % (Time.now.to_i - 30.days) }
|
87
|
+
res.stub(:content).and_return(@cheated)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "raise SignatureError" do
|
92
|
+
req = @network.new_async_action_request
|
93
|
+
req.server_time
|
94
|
+
req.response_hook = @cheat
|
95
|
+
expect{ req.send_request }.to raise_error(Libgss::ActionRequest::SignatureError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "with skip_verifying_signature" do
|
99
|
+
@network.skip_verifying_signature = true
|
100
|
+
req = @network.new_async_action_request
|
101
|
+
req.server_time
|
102
|
+
req.response_hook = @cheat
|
103
|
+
expect{ req.send_request }.to_not raise_error(Libgss::ActionRequest::SignatureError)
|
104
|
+
# 検証をスキップしているので、通信経路上で改ざんされたデータを取得できてしまう
|
105
|
+
# ここでは「実行中」であるはずの結果が、改ざんされたものになってしまう
|
106
|
+
req.outputs.to_a.should be_a(Array)
|
107
|
+
req.outputs.first.should be_a(Hash)
|
108
|
+
req.outputs.first["id"].should == 1
|
109
|
+
req.outputs.first["result"].should be_a(Integer)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "async_action_request" do
|
115
|
+
context "default" do
|
116
|
+
before{ @network = new_network.login! }
|
117
|
+
it_should_behave_like "async_action_request with response_signature"
|
118
|
+
end
|
119
|
+
|
120
|
+
context "1.0.0" do
|
121
|
+
before{ @network = new_network_with_options(api_version: "1.0.0").login! }
|
122
|
+
it_should_behave_like "async_action_request with response_signature"
|
123
|
+
end
|
124
|
+
|
125
|
+
context "1.1.0" do
|
126
|
+
before{ @network = new_network_with_options(api_version: "1.1.0").login! }
|
127
|
+
it_should_behave_like "async_action_request with response_signature"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
shared_examples_for "async_status_request with response_signature" do
|
135
|
+
context "valid" do
|
136
|
+
it do
|
137
|
+
req = @network.new_async_action_request
|
138
|
+
req.server_time
|
139
|
+
req.send_request
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "invalid response body" do
|
144
|
+
before do
|
145
|
+
# 通信経路上で実際の時刻より過去の時刻を返すようにレスポンスを改ざんしていることを
|
146
|
+
# 想定して、レスポンスオブジェクトのcontentだけ内容を書き換えます。
|
147
|
+
@cheat = Proc.new do |res|
|
148
|
+
cheated = res.content.dup
|
149
|
+
cheated.sub!(/"result":(\d+)/){ "\"result\":%d" % ($1.to_i - 30.days) }
|
150
|
+
cheated.sub!(/\\"result\\":(\d+)/){ "\\\"result\\\":%d" % ($1.to_i - 30.days) }
|
151
|
+
res.stub(:content).and_return(cheated)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
it "raise SignatureError" do
|
156
|
+
req = @network.new_async_action_request
|
157
|
+
req.server_time
|
158
|
+
req.response_hook = @cheat
|
159
|
+
expect{ req.async_status([@async_action02.action_id]) }.to raise_error(Libgss::ActionRequest::SignatureError)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "with skip_verifying_signature" do
|
163
|
+
@network.skip_verifying_signature = true
|
164
|
+
req = @network.new_async_action_request
|
165
|
+
req.server_time
|
166
|
+
req.response_hook = @cheat
|
167
|
+
expect{ req.async_status([@async_action02.action_id]) }.to_not raise_error(Libgss::ActionRequest::SignatureError)
|
168
|
+
# 検証をスキップしているので、通信経路上で改ざんされたデータを取得できてしまう
|
169
|
+
req.outputs.to_a.should be_a(Array)
|
170
|
+
req.outputs.first.should be_a(Hash)
|
171
|
+
req.outputs.first["id"].should == @async_action02.action_id
|
172
|
+
req.outputs.first["result"].should be_a(Integer)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "async_status_request" do
|
178
|
+
before do
|
179
|
+
Player.delete_all
|
180
|
+
AsyncAction.delete_all
|
181
|
+
@async_action02 = FactoryGirl.create(:async_action02)
|
182
|
+
@player01 = @async_action02.player
|
183
|
+
end
|
184
|
+
|
185
|
+
context "default" do
|
186
|
+
before{ @network = new_network(@player01.player_id).login! }
|
187
|
+
it_should_behave_like "async_status_request with response_signature"
|
188
|
+
end
|
189
|
+
|
190
|
+
context "1.0.0" do
|
191
|
+
before{ @network = new_network_with_options({api_version: "1.0.0"}, @player01.player_id).login! }
|
192
|
+
it_should_behave_like "async_status_request with response_signature"
|
193
|
+
end
|
194
|
+
|
195
|
+
context "1.1.0" do
|
196
|
+
before{ @network = new_network_with_options({api_version: "1.1.0"}, @player01.player_id).login! }
|
197
|
+
it_should_behave_like "async_status_request with response_signature"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,8 +4,8 @@ require 'libgss'
|
|
4
4
|
require 'tengine/support/yaml_with_erb'
|
5
5
|
|
6
6
|
require 'fontana_client_support'
|
7
|
-
require 'mongoid'
|
8
7
|
|
8
|
+
require 'mongoid'
|
9
9
|
|
10
10
|
Mongoid.logger.level = 0
|
11
11
|
log_path = File.expand_path("../../tmp/test.log", __FILE__)
|
@@ -21,6 +21,8 @@ require 'active_support/dependencies'
|
|
21
21
|
|
22
22
|
Time.zone = ActiveSupport::TimeZone.zones_map["Tokyo"]
|
23
23
|
|
24
|
+
# require File.expand_path("../../fontana_sample/spec/spec_helper", __FILE__)
|
25
|
+
|
24
26
|
d = File.expand_path("../support/models", __FILE__)
|
25
27
|
"Directory not found: #{d.inspect}" unless Dir.exist?(d)
|
26
28
|
ActiveSupport::Dependencies.autoload_paths << d
|
@@ -32,6 +34,7 @@ require 'factory_girl'
|
|
32
34
|
FactoryGirl.find_definitions
|
33
35
|
|
34
36
|
RSpec.configure do |config|
|
37
|
+
|
35
38
|
# iOS開発環境が整っていない場合、SSLで接続する https://sandbox.itunes.apple.com/verifyreceipt が
|
36
39
|
# オレオレ証明書を使っているので、その検証をができなくてエラーになってしまいます。
|
37
40
|
# 本来ならば、信頼する証明書として追加する方が良いと思われますが、
|
@@ -40,5 +43,6 @@ RSpec.configure do |config|
|
|
40
43
|
# ように設定してしまいます。
|
41
44
|
require 'openssl'
|
42
45
|
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
|
46
|
+
|
43
47
|
config.include FactoryGirl::Syntax::Methods
|
44
48
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libgss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- akima
|
@@ -196,7 +196,7 @@ files:
|
|
196
196
|
- libgss.gemspec
|
197
197
|
- spec/factories/async_action.rb
|
198
198
|
- spec/factories/client_release.rb
|
199
|
-
- spec/factories/device_type.rb
|
199
|
+
- spec/factories/client_release/device_type.rb
|
200
200
|
- spec/factories/game_data.rb
|
201
201
|
- spec/factories/player.rb
|
202
202
|
- spec/libgss/action_request_spec.rb
|
@@ -212,6 +212,7 @@ files:
|
|
212
212
|
- spec/libgss/asset_request_spec.rb
|
213
213
|
- spec/libgss/async_action_request_spec.rb
|
214
214
|
- spec/libgss/network_spec.rb
|
215
|
+
- spec/libgss/response_signatrue_spec.rb
|
215
216
|
- spec/protected_assets/Icon.png
|
216
217
|
- spec/public_assets/Default.png
|
217
218
|
- spec/spec_helper.rb
|
@@ -249,7 +250,7 @@ summary: network library for Groovenauts GSS
|
|
249
250
|
test_files:
|
250
251
|
- spec/factories/async_action.rb
|
251
252
|
- spec/factories/client_release.rb
|
252
|
-
- spec/factories/device_type.rb
|
253
|
+
- spec/factories/client_release/device_type.rb
|
253
254
|
- spec/factories/game_data.rb
|
254
255
|
- spec/factories/player.rb
|
255
256
|
- spec/libgss/action_request_spec.rb
|
@@ -265,6 +266,7 @@ test_files:
|
|
265
266
|
- spec/libgss/asset_request_spec.rb
|
266
267
|
- spec/libgss/async_action_request_spec.rb
|
267
268
|
- spec/libgss/network_spec.rb
|
269
|
+
- spec/libgss/response_signatrue_spec.rb
|
268
270
|
- spec/protected_assets/Icon.png
|
269
271
|
- spec/public_assets/Default.png
|
270
272
|
- spec/spec_helper.rb
|