wix-apps 0.0.3 → 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/.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
|