wix-apps 0.0.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -1
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +10 -6
- data/Gemfile +0 -2
- data/Guardfile +1 -1
- data/README.md +64 -8
- data/Rakefile +7 -3
- data/lib/wix-apps.rb +1 -2
- data/lib/wix-apps/signed_instance.rb +85 -34
- data/lib/wix-apps/signed_instance_middleware.rb +48 -42
- data/lib/wix-apps/version.rb +1 -1
- data/spec/lib/wix-apps/signed_instance_middleware_spec.rb +133 -67
- data/spec/lib/wix-apps/signed_instance_spec.rb +120 -55
- data/spec/spec_helper.rb +42 -1
- data/wix-apps.gemspec +18 -14
- metadata +69 -49
- data/.rvmrc +0 -52
data/lib/wix-apps/version.rb
CHANGED
@@ -1,108 +1,174 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
def in_middleware
|
4
|
+
expect(app).to receive(:call) do |env|
|
5
|
+
yield(env)
|
6
|
+
[200, {}, []]
|
7
|
+
end
|
8
|
+
|
9
|
+
response
|
10
|
+
end
|
11
|
+
|
3
12
|
describe Wix::Apps::SignedInstanceMiddleware do
|
4
13
|
include Rack::Test::Methods
|
5
14
|
|
6
15
|
let(:app) { lambda { |env| [200, {}, []] } }
|
7
16
|
let(:secret) { 'd245bbf8-57eb-49d6-aeff-beff6d82cd39' }
|
8
|
-
|
9
|
-
|
10
|
-
|
17
|
+
let(:middleware) { Wix::Apps::SignedInstanceMiddleware.new(
|
18
|
+
app,
|
19
|
+
secured_paths: ['/wix', %r{\A/secured_paths_\d+\z}],
|
20
|
+
paths: ['/wix_path', %r{\A/paths_\d+\z}],
|
21
|
+
secret_key: secret)
|
22
|
+
}
|
11
23
|
let(:mock_request) { Rack::MockRequest.new(middleware) }
|
24
|
+
let(:instance) { sign(params_required) }
|
12
25
|
|
13
|
-
|
14
|
-
let(:response) { mock_request.get('/wix', params: { 'instance' => instance }) }
|
15
|
-
|
16
|
-
describe "Unsecured paths" do
|
26
|
+
describe 'a request to an unsecured path' do
|
17
27
|
let(:response) { mock_request.get('/') }
|
18
|
-
it(
|
28
|
+
it('returns a 200') do
|
29
|
+
expect(response.status).to eq 200
|
30
|
+
end
|
19
31
|
end
|
20
32
|
|
21
|
-
describe
|
22
|
-
describe "without instanse" do
|
23
|
-
let(:response) { mock_request.get('/wix') }
|
24
|
-
it("returns a 401") { response.status.should == 401 }
|
25
|
-
end
|
33
|
+
describe 'a request to' do
|
26
34
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
35
|
+
shared_examples_for 'a request to a path' do
|
36
|
+
describe 'without an instance' do
|
37
|
+
let(:response) { mock_request.get(path) }
|
38
|
+
|
39
|
+
it('returns a 200') do
|
40
|
+
expect(response.status).to eq 200
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'contains the instance key in the env' do
|
44
|
+
in_middleware { |env| expect(env.has_key?('wix.instance')).to eq true }
|
45
|
+
end
|
31
46
|
|
32
|
-
|
33
|
-
|
47
|
+
it 'contains a nil instance in env' do
|
48
|
+
in_middleware { |env| expect(env['wix.instance']).to be_nil }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:response) { mock_request.get('/wix_path', params: {'instance' => instance}) }
|
54
|
+
|
55
|
+
describe 'with an empty instance' do
|
56
|
+
let(:instance) { nil }
|
57
|
+
|
58
|
+
it('returns a 403') do
|
59
|
+
expect(response.status).to eq 403
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
34
63
|
|
35
|
-
describe
|
36
|
-
it "have instance_id" do
|
37
|
-
app.should_receive(:call) do |arg|
|
38
|
-
arg['rack.request.query_hash']['parsed_instance']['instance_id']
|
39
|
-
.should eq('b8140e4d-475d-48ed-819f-bad0de447069')
|
64
|
+
describe 'with a valid anonymous instance' do
|
40
65
|
|
41
|
-
|
42
|
-
end
|
66
|
+
let(:instance) { sign(params_required) }
|
43
67
|
|
44
|
-
|
68
|
+
it('returns a 200') do
|
69
|
+
expect(response.status).to eq 200
|
45
70
|
end
|
46
71
|
|
47
|
-
it
|
48
|
-
|
49
|
-
|
50
|
-
.should eq(DateTime.parse("2012-08-11T13:56:44.635Z"))
|
51
|
-
[200, {}, []]
|
52
|
-
end
|
72
|
+
it 'contains the instance key in the env' do
|
73
|
+
in_middleware { |env| expect(env.has_key?('wix.instance')).to eq true }
|
74
|
+
end
|
53
75
|
|
54
|
-
|
76
|
+
it 'has an instance_id' do
|
77
|
+
in_middleware { |env| expect(env['wix.instance'].instance_id).to eq params_required[:instanceId] }
|
55
78
|
end
|
79
|
+
|
56
80
|
end
|
81
|
+
end
|
57
82
|
|
58
|
-
|
59
|
-
|
83
|
+
describe 'a path matched statically' do
|
84
|
+
let(:path) { '/wix_path' }
|
85
|
+
it_behaves_like 'a request to a path'
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'a path matched by regex' do
|
89
|
+
let(:path) { '/paths_9' }
|
90
|
+
it_behaves_like 'a request to a path'
|
91
|
+
end
|
92
|
+
|
93
|
+
shared_examples_for 'a request to a secured path' do
|
94
|
+
describe 'without an instance' do
|
95
|
+
let(:response) { mock_request.get(path) }
|
96
|
+
it('returns a 401') do
|
97
|
+
expect(response.status).to eq 401
|
98
|
+
end
|
99
|
+
end
|
60
100
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
101
|
+
describe 'with an invalid instance' do
|
102
|
+
let(:instance) { 'invalid.instance' }
|
103
|
+
it('returns a 403') do
|
104
|
+
expect(response.status).to eq 403
|
105
|
+
end
|
106
|
+
end
|
67
107
|
|
68
|
-
|
108
|
+
describe 'with an empty instance' do
|
109
|
+
let(:instance) { nil }
|
110
|
+
it('returns a 403') do
|
111
|
+
expect(response.status).to eq 403
|
69
112
|
end
|
113
|
+
end
|
70
114
|
|
71
|
-
|
72
|
-
app.should_receive(:call) do |arg|
|
73
|
-
arg['rack.request.query_hash']['parsed_instance']['permissions']
|
74
|
-
.should be_nil
|
75
|
-
[200, {}, []]
|
76
|
-
end
|
115
|
+
let(:response) { mock_request.get(path, params: {'instance' => instance}) }
|
77
116
|
|
78
|
-
|
117
|
+
describe 'with a valid anonymous instance' do
|
118
|
+
it('returns a 200') do
|
119
|
+
expect(response.status).to eq 200
|
79
120
|
end
|
121
|
+
|
122
|
+
it 'has an instance_id' do
|
123
|
+
in_middleware { |env| expect(env['wix.instance'].instance_id).to eq params_required[:instanceId] }
|
124
|
+
end
|
125
|
+
|
80
126
|
end
|
81
127
|
|
128
|
+
describe 'with a valid logged in instance' do
|
129
|
+
let(:params_with_user) {
|
130
|
+
params_required.merge(uid: 'c713982b-9161-49bc-9ff5-67502e4b705b')
|
131
|
+
}
|
82
132
|
|
83
|
-
|
84
|
-
let(:instance) { 'zPsXLAaMznRbzXUiBo51bNzjKhVRo-GU5U4wSqyxzIg.eyJpbnN0YW5jZUlkIjoiOWY5YzVjMTYtNTljOC00NzA4LThjMjUtODU1NTA1ZGFhOTU0Iiwic2lnbkRhdGUiOiIyMDEyLTA4LTEyVDEwOjExOjIyLjkzNFoiLCJ1aWQiOiIyOWQ4MjA0YS0zYjgyLTRhOTgtOGQ4Ni0yNDY0YTZiODM2ZGEiLCJwZXJtaXNzaW9ucyI6Ik9XTkVSIn0' }
|
133
|
+
let(:instance) { sign(params_with_user) }
|
85
134
|
|
86
|
-
it
|
87
|
-
|
88
|
-
|
89
|
-
.should eq('29d8204a-3b82-4a98-8d86-2464a6b836da')
|
90
|
-
[200, {}, []]
|
91
|
-
end
|
135
|
+
it 'has a user_id' do
|
136
|
+
in_middleware { |env| expect(env['wix.instance'].uid).to eq params_with_user[:uid] }
|
137
|
+
end
|
92
138
|
|
93
|
-
|
139
|
+
it 'does not have permissions' do
|
140
|
+
in_middleware { |env| expect(env['wix.instance'].permissions).to eq '' }
|
94
141
|
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe 'with a valid owner instance' do
|
95
145
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
146
|
+
let(:params_with_owner) {
|
147
|
+
params_required.merge(uid: '92771668-366f-4ec6-be21-b32c78e7b734', permissions: 'OWNER')
|
148
|
+
}
|
149
|
+
|
150
|
+
let(:instance) { sign(params_with_owner) }
|
151
|
+
|
152
|
+
it 'have a user_id' do
|
153
|
+
in_middleware { |env| expect(env['wix.instance'].uid).to eq params_with_owner[:uid] }
|
154
|
+
end
|
102
155
|
|
103
|
-
|
156
|
+
it 'have permissions' do
|
157
|
+
in_middleware { |env| expect(env['wix.instance'].permissions).to eq params_with_owner[:permissions] }
|
104
158
|
end
|
105
159
|
end
|
106
160
|
end
|
161
|
+
|
162
|
+
describe 'a secured path matched staically' do
|
163
|
+
let(:path) { '/wix' }
|
164
|
+
it_behaves_like 'a request to a secured path'
|
165
|
+
end
|
166
|
+
|
167
|
+
describe 'a secured path matched by regex' do
|
168
|
+
let(:path) { '/secured_paths_10' }
|
169
|
+
it_behaves_like 'a request to a secured path'
|
170
|
+
end
|
171
|
+
|
107
172
|
end
|
108
|
-
|
173
|
+
|
174
|
+
end
|
@@ -1,104 +1,169 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
describe 'signing test method' do
|
3
4
|
|
4
|
-
describe Wix::Apps::SignedInstance do
|
5
5
|
let(:raw_signed_instance) { 'naQKltLRVJwLVN90qQYpmmyzkVqFIH0hpvETYuivA1U.eyJpbnN0YW5jZUlkIjoiOWY5YzVjMTYtNTljOC00NzA4LThjMjUtODU1NTA1ZGFhOTU0Iiwic2lnbkRhdGUiOiIyMDEyLTA4LTA4VDE5OjQ3OjMxLjYyNFoiLCJ1aWQiOm51bGwsInBlcm1pc3Npb25zIjpudWxsfQ' }
|
6
|
-
let(:invalid_raw_signed_instance) {'Incorect Raw Signed Instance'}
|
7
6
|
let(:raw_signed_instance_with_user_id) { 'K78r2uwAQbvA68u-bXxn2cdIUFMZIp8v9XfA_hd-iyo.eyJpbnN0YW5jZUlkIjoiOWY5YzVjMTYtNTljOC00NzA4LThjMjUtODU1NTA1ZGFhOTU0Iiwic2lnbkRhdGUiOiIyMDEyLTA4LTA4VDIyOjEwOjU2Ljg3NVoiLCJ1aWQiOiIyOWQ4MjA0YS0zYjgyLTRhOTgtOGQ4Ni0yNDY0YTZiODM2ZGEiLCJwZXJtaXNzaW9ucyI6bnVsbH0' }
|
8
7
|
let(:raw_signed_in_owner_mode) { 'AjQ3BniGXfSOjKw4ej_V0kh4-WF5eB2IRnbvsak9kwc.eyJpbnN0YW5jZUlkIjoiOWY5YzVjMTYtNTljOC00NzA4LThjMjUtODU1NTA1ZGFhOTU0Iiwic2lnbkRhdGUiOiIyMDEyLTA4LTA4VDIyOjEyOjE2LjU4OVoiLCJ1aWQiOiIyOWQ4MjA0YS0zYjgyLTRhOTgtOGQ4Ni0yNDY0YTZiODM2ZGEiLCJwZXJtaXNzaW9ucyI6Ik9XTkVSIn0' }
|
9
8
|
|
10
|
-
|
9
|
+
it 'encodes correctly 1/3' do
|
10
|
+
decoded_json = decode(raw_signed_instance)
|
11
|
+
expect(sign_string(decoded_json)).to eq raw_signed_instance
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
it 'encodes correctly 2/3' do
|
15
|
+
decoded_json = decode(raw_signed_instance_with_user_id)
|
16
|
+
expect(sign_string(decoded_json)).to eq raw_signed_instance_with_user_id
|
17
|
+
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
it 'encodes correctly 3/3' do
|
20
|
+
decoded_json = decode(raw_signed_in_owner_mode)
|
21
|
+
expect(sign_string(decoded_json)).to eq raw_signed_in_owner_mode
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Wix::Apps::SignedInstance do
|
27
|
+
|
28
|
+
let(:params_with_user) {
|
29
|
+
params_required.merge(uid: 'c713982b-9161-49bc-9ff5-67502e4b705b')
|
30
|
+
}
|
31
|
+
|
32
|
+
let(:params_with_owner) {
|
33
|
+
params_required.merge(uid: '92771668-366f-4ec6-be21-b32c78e7b734', permissions: 'OWNER')
|
34
|
+
}
|
35
|
+
|
36
|
+
let(:invalid_raw_signed_instance) { 'Invalid signature format' }
|
37
|
+
|
38
|
+
describe 'Initialization' do
|
39
|
+
|
40
|
+
subject { Wix::Apps::SignedInstance.new(sign(params_required), secret_key: SECRET_KEY) }
|
41
|
+
|
42
|
+
it 'parses instanceId' do
|
43
|
+
expect(subject.instance_id).to eq params_required[:instanceId]
|
19
44
|
end
|
20
45
|
|
21
|
-
it
|
22
|
-
subject.
|
46
|
+
it 'parses sign_date as DateTime' do
|
47
|
+
expect(subject.sign_date).to be_kind_of DateTime
|
23
48
|
end
|
24
49
|
|
25
|
-
it
|
26
|
-
subject.sign_date.
|
50
|
+
it 'parses sign_date' do
|
51
|
+
expect(subject.sign_date.rfc3339).to eq params_required[:signDate]
|
27
52
|
end
|
28
53
|
|
29
|
-
it
|
30
|
-
subject.
|
54
|
+
it 'returns nil as user id' do
|
55
|
+
expect(subject.uid).to be_nil
|
31
56
|
end
|
32
57
|
|
33
|
-
it
|
34
|
-
subject.
|
58
|
+
it 'parses permissions' do
|
59
|
+
expect(subject.permissions).to eq params_required[:permissions]
|
35
60
|
end
|
36
61
|
|
37
|
-
|
38
|
-
subject
|
62
|
+
it 'parses ipAndPort' do
|
63
|
+
expect(subject.ip_and_port).to eq params_required[:ipAndPort]
|
64
|
+
end
|
39
65
|
|
40
|
-
|
41
|
-
|
42
|
-
|
66
|
+
it 'parses vendorProductId' do
|
67
|
+
expect(subject.vendor_product_id).to eq params_required[:vendorProductId]
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'parses aid' do
|
71
|
+
expect(subject.aid).to eq params_required[:aid]
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'parses siteOwnerId' do
|
75
|
+
expect(subject.site_owner_id).to eq params_required[:siteOwnerId]
|
76
|
+
end
|
43
77
|
|
78
|
+
it 'has owner not logged in' do
|
79
|
+
expect(subject.owner_logged_in?).to eq false
|
44
80
|
end
|
45
81
|
|
46
|
-
describe
|
47
|
-
subject { Wix::Apps::SignedInstance.new(
|
48
|
-
|
49
|
-
|
82
|
+
describe 'With a user id' do
|
83
|
+
subject { Wix::Apps::SignedInstance.new(sign(params_with_user), secret_key: SECRET_KEY) }
|
84
|
+
|
85
|
+
it 'parses user id' do
|
86
|
+
expect(subject.uid).to eq params_with_user[:uid]
|
50
87
|
end
|
51
88
|
|
52
|
-
it
|
53
|
-
subject.
|
89
|
+
it 'has owner not logged in' do
|
90
|
+
expect(subject.owner_logged_in?).to eq false
|
54
91
|
end
|
92
|
+
|
55
93
|
end
|
56
|
-
end
|
57
94
|
|
58
|
-
|
95
|
+
describe 'with an owner' do
|
96
|
+
subject { Wix::Apps::SignedInstance.new(sign(params_with_owner), secret_key: SECRET_KEY) }
|
59
97
|
|
60
|
-
|
61
|
-
|
98
|
+
it 'has owner logged in' do
|
99
|
+
expect(subject.owner_logged_in?).to eq true
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'parses permissions' do
|
103
|
+
expect(subject.permissions).to eq 'OWNER'
|
104
|
+
end
|
62
105
|
|
63
|
-
it
|
64
|
-
expect
|
106
|
+
it 'has owner permissions' do
|
107
|
+
expect(subject.owner_permissions?).to eq true
|
65
108
|
end
|
66
109
|
end
|
67
110
|
|
68
|
-
describe
|
69
|
-
subject { Wix::Apps::SignedInstance.new(raw_signed_instance, :secret => 'another-secret') }
|
111
|
+
describe 'with missing required params' do
|
70
112
|
|
71
|
-
|
72
|
-
|
113
|
+
params_required.keys.each do |key|
|
114
|
+
params = params_required.reject { |k, _| k == key }
|
115
|
+
subject { Wix::Apps::SignedInstance.new(sign(params), secret_key: SECRET_KEY) }
|
116
|
+
it "raises an exception when #{key} is missing" do
|
117
|
+
expect { subject }.to raise_error Wix::Apps::SignedInstanceParseError
|
118
|
+
end
|
73
119
|
end
|
120
|
+
|
74
121
|
end
|
122
|
+
end
|
75
123
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
124
|
+
describe 'initialization without `strict_properties`' do
|
125
|
+
let(:params) { {instanceId: '123456789'} }
|
126
|
+
subject { Wix::Apps::SignedInstance.new(sign(params), secret_key: SECRET_KEY, strict_properties: false) }
|
127
|
+
|
128
|
+
it 'has an instance_id' do
|
129
|
+
expect(subject.instance_id).to eq params[:instanceId]
|
80
130
|
end
|
81
131
|
end
|
82
132
|
|
83
|
-
describe
|
84
|
-
|
85
|
-
|
86
|
-
|
133
|
+
describe 'signature validation' do
|
134
|
+
|
135
|
+
describe 'with an invalid format' do
|
136
|
+
subject { Wix::Apps::SignedInstance.new(invalid_raw_signed_instance, secret_key: SECRET_KEY) }
|
137
|
+
|
138
|
+
it 'raise SignedInstance::ParseError' do
|
139
|
+
expect { subject }.to raise_error Wix::Apps::SignedInstanceParseError
|
87
140
|
end
|
88
141
|
end
|
89
142
|
|
90
|
-
describe
|
91
|
-
subject { Wix::Apps::SignedInstance.new(
|
92
|
-
|
93
|
-
|
143
|
+
describe 'without a secret' do
|
144
|
+
subject { Wix::Apps::SignedInstance.new(sign(params_required)) }
|
145
|
+
|
146
|
+
it 'raises SignedInstanceNoSecretKey' do
|
147
|
+
expect { subject }.to raise_error Wix::Apps::SignedInstanceNoSecretKey
|
94
148
|
end
|
95
149
|
end
|
96
150
|
|
97
|
-
describe
|
98
|
-
subject { Wix::Apps::SignedInstance.new(
|
99
|
-
|
100
|
-
|
151
|
+
describe 'with an incorrect secret' do
|
152
|
+
subject { Wix::Apps::SignedInstance.new(sign(params_required), secret_key: 'another-secret') }
|
153
|
+
|
154
|
+
it 'raise SignedInstanceParseError' do
|
155
|
+
expect { subject }.to raise_error Wix::Apps::SignedInstanceParseError
|
101
156
|
end
|
102
157
|
end
|
158
|
+
|
159
|
+
describe 'with a valid signature' do
|
160
|
+
subject { Wix::Apps::SignedInstance.new(sign(params_required), secret_key: SECRET_KEY) }
|
161
|
+
|
162
|
+
it 'should instantiate' do
|
163
|
+
expect(subject).to be_instance_of Wix::Apps::SignedInstance
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
103
167
|
end
|
104
|
-
|
168
|
+
|
169
|
+
end
|