tentd 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +9 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +49 -0
- data/Rakefile +8 -0
- data/bin/tent-server +3 -0
- data/lib/tentd.rb +31 -0
- data/lib/tentd/api.rb +58 -0
- data/lib/tentd/api/apps.rb +196 -0
- data/lib/tentd/api/authentication_finalize.rb +12 -0
- data/lib/tentd/api/authentication_lookup.rb +27 -0
- data/lib/tentd/api/authentication_verification.rb +50 -0
- data/lib/tentd/api/authorizable.rb +21 -0
- data/lib/tentd/api/authorization.rb +14 -0
- data/lib/tentd/api/core_profile_data.rb +45 -0
- data/lib/tentd/api/followers.rb +218 -0
- data/lib/tentd/api/followings.rb +241 -0
- data/lib/tentd/api/groups.rb +161 -0
- data/lib/tentd/api/middleware.rb +32 -0
- data/lib/tentd/api/posts.rb +373 -0
- data/lib/tentd/api/profile.rb +78 -0
- data/lib/tentd/api/router.rb +123 -0
- data/lib/tentd/api/router/caching_headers.rb +49 -0
- data/lib/tentd/api/router/extract_params.rb +88 -0
- data/lib/tentd/api/router/serialize_response.rb +38 -0
- data/lib/tentd/api/user_lookup.rb +10 -0
- data/lib/tentd/core_ext/hash/slice.rb +29 -0
- data/lib/tentd/datamapper/array_property.rb +23 -0
- data/lib/tentd/datamapper/query.rb +19 -0
- data/lib/tentd/json_patch.rb +181 -0
- data/lib/tentd/model.rb +30 -0
- data/lib/tentd/model/app.rb +68 -0
- data/lib/tentd/model/app_authorization.rb +113 -0
- data/lib/tentd/model/follower.rb +105 -0
- data/lib/tentd/model/following.rb +100 -0
- data/lib/tentd/model/group.rb +24 -0
- data/lib/tentd/model/mention.rb +19 -0
- data/lib/tentd/model/notification_subscription.rb +56 -0
- data/lib/tentd/model/permissible.rb +227 -0
- data/lib/tentd/model/permission.rb +28 -0
- data/lib/tentd/model/post.rb +178 -0
- data/lib/tentd/model/post_attachment.rb +27 -0
- data/lib/tentd/model/post_version.rb +64 -0
- data/lib/tentd/model/profile_info.rb +80 -0
- data/lib/tentd/model/random_public_id.rb +46 -0
- data/lib/tentd/model/serializable.rb +58 -0
- data/lib/tentd/model/type_properties.rb +36 -0
- data/lib/tentd/model/user.rb +39 -0
- data/lib/tentd/model/user_scoped.rb +14 -0
- data/lib/tentd/notifications.rb +13 -0
- data/lib/tentd/notifications/girl_friday.rb +30 -0
- data/lib/tentd/notifications/sidekiq.rb +50 -0
- data/lib/tentd/tent_type.rb +20 -0
- data/lib/tentd/tent_version.rb +41 -0
- data/lib/tentd/version.rb +3 -0
- data/spec/fabricators/app_authorizations_fabricator.rb +5 -0
- data/spec/fabricators/apps_fabricator.rb +11 -0
- data/spec/fabricators/followers_fabricator.rb +14 -0
- data/spec/fabricators/followings_fabricator.rb +17 -0
- data/spec/fabricators/groups_fabricator.rb +3 -0
- data/spec/fabricators/mentions_fabricator.rb +3 -0
- data/spec/fabricators/notification_subscriptions_fabricator.rb +4 -0
- data/spec/fabricators/permissions_fabricator.rb +1 -0
- data/spec/fabricators/post_attachments_fabricator.rb +8 -0
- data/spec/fabricators/post_versions_fabricator.rb +12 -0
- data/spec/fabricators/posts_fabricator.rb +12 -0
- data/spec/fabricators/profile_infos_fabricator.rb +30 -0
- data/spec/integration/api/apps_spec.rb +466 -0
- data/spec/integration/api/followers_spec.rb +535 -0
- data/spec/integration/api/followings_spec.rb +688 -0
- data/spec/integration/api/groups_spec.rb +207 -0
- data/spec/integration/api/posts_spec.rb +874 -0
- data/spec/integration/api/profile_spec.rb +285 -0
- data/spec/integration/api/router_spec.rb +102 -0
- data/spec/integration/model/app_authorization_spec.rb +59 -0
- data/spec/integration/model/app_spec.rb +63 -0
- data/spec/integration/model/follower_spec.rb +344 -0
- data/spec/integration/model/following_spec.rb +97 -0
- data/spec/integration/model/group_spec.rb +39 -0
- data/spec/integration/model/notification_subscription_spec.rb +145 -0
- data/spec/integration/model/post_spec.rb +658 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/expect_server.rb +3 -0
- data/spec/support/json_request.rb +54 -0
- data/spec/support/with_constant.rb +23 -0
- data/spec/support/with_warnings.rb +6 -0
- data/spec/unit/api/authentication_finalize_spec.rb +45 -0
- data/spec/unit/api/authentication_lookup_spec.rb +65 -0
- data/spec/unit/api/authentication_verification_spec.rb +50 -0
- data/spec/unit/api/authorizable_spec.rb +50 -0
- data/spec/unit/api/authorization_spec.rb +44 -0
- data/spec/unit/api/caching_headers_spec.rb +121 -0
- data/spec/unit/core_profile_data_spec.rb +64 -0
- data/spec/unit/json_patch_spec.rb +407 -0
- data/spec/unit/tent_type_spec.rb +28 -0
- data/spec/unit/tent_version_spec.rb +68 -0
- data/tentd.gemspec +36 -0
- metadata +435 -0
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TentD::API::Profile do
|
4
|
+
def app
|
5
|
+
TentD::API.new
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:env) { {} }
|
9
|
+
let(:params) { Hash.new }
|
10
|
+
|
11
|
+
let(:authorized_info_types) { [] }
|
12
|
+
let(:authorized_scopes) { [] }
|
13
|
+
let(:app_authorization) do
|
14
|
+
Fabricate(
|
15
|
+
:app_authorization,
|
16
|
+
:app => Fabricate(:app),
|
17
|
+
:profile_info_types => authorized_info_types,
|
18
|
+
:scopes => authorized_scopes
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:basic_info_type) { "https://tent.io/types/info/basic/v0.1.0" }
|
23
|
+
let(:basic_info_content) do
|
24
|
+
{
|
25
|
+
"name" => "John Smith",
|
26
|
+
"age" => 21
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:work_history_type) { "https://tent.io/types/info/work-history/v0.1.0" }
|
31
|
+
let(:work_history_content) do
|
32
|
+
{
|
33
|
+
"employers" => ["Foo Corp"]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def url_encode_type(type)
|
38
|
+
URI.encode(type, ":/")
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_info(type, content, options = {})
|
42
|
+
Fabricate(:profile_info, :public => options[:public], :type => type, :content => content)
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'GET /profile' do
|
46
|
+
context 'when read_profile scope authorized' do
|
47
|
+
let(:authorized_scopes) { [:read_profile] }
|
48
|
+
before { env['current_auth'] = app_authorization }
|
49
|
+
|
50
|
+
context 'when authorized for all info types' do
|
51
|
+
let(:authorized_info_types) { ['all'] }
|
52
|
+
|
53
|
+
it 'should return all info types' do
|
54
|
+
TentD::Model::ProfileInfo.all.destroy
|
55
|
+
|
56
|
+
profile_infos = []
|
57
|
+
profile_infos << Fabricate(:profile_info, :public => false)
|
58
|
+
profile_infos << Fabricate(:basic_profile_info, :public => false)
|
59
|
+
|
60
|
+
json_get '/profile', params, env
|
61
|
+
expect(last_response.body).to eq({
|
62
|
+
"#{ profile_infos.first.type.uri }" => profile_infos.first.content.merge(:permissions => profile_infos.first.permissions_json),
|
63
|
+
"#{ profile_infos.last.type.uri }" => profile_infos.last.content.merge(:permissions => profile_infos.first.permissions_json)
|
64
|
+
}.to_json)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when authorized for specific info types' do
|
69
|
+
let(:authorized_info_types) { ['https://tent.io/types/info/basic'] }
|
70
|
+
|
71
|
+
it 'should only return authorized info types' do
|
72
|
+
TentD::Model::ProfileInfo.all.destroy
|
73
|
+
|
74
|
+
profile_infos = []
|
75
|
+
profile_infos << Fabricate(:profile_info, :public => false, :type => "https://tent.io/types/info/basic/v0.1.0")
|
76
|
+
profile_infos << Fabricate(:profile_info, :public => false)
|
77
|
+
|
78
|
+
json_get '/profile', params, env
|
79
|
+
expect(last_response.body).to eq({
|
80
|
+
"#{ profile_infos.first.type.uri }" => profile_infos.first.content.merge(:permissions => profile_infos.first.permissions_json)
|
81
|
+
}.to_json)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when read_profile scope unauthorized' do
|
87
|
+
it 'should only return public profile into types' do
|
88
|
+
TentD::Model::ProfileInfo.all.destroy
|
89
|
+
|
90
|
+
profile_infos = []
|
91
|
+
profile_infos << Fabricate(:profile_info, :public => true)
|
92
|
+
profile_infos << Fabricate(:basic_profile_info, :public => false)
|
93
|
+
|
94
|
+
json_get '/profile', params, env
|
95
|
+
expect(last_response.body).to eq({
|
96
|
+
"#{ profile_infos.first.type.uri }" => profile_infos.first.content.merge(:permissions => profile_infos.first.permissions_json)
|
97
|
+
}.to_json)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'PUT /profile/:type_url' do
|
103
|
+
before { env['current_auth'] = app_authorization }
|
104
|
+
|
105
|
+
context 'when authorized' do
|
106
|
+
let(:authorized_scopes) { [:write_profile] }
|
107
|
+
|
108
|
+
can_update_basic_info_type = proc do
|
109
|
+
it 'should update info type' do
|
110
|
+
info = create_info(basic_info_type, basic_info_content, :public => false)
|
111
|
+
|
112
|
+
expect(info.type.uri).to eq(basic_info_type)
|
113
|
+
|
114
|
+
data = {
|
115
|
+
"name" => "John Doe"
|
116
|
+
}
|
117
|
+
|
118
|
+
json_put "/profile/#{url_encode_type(basic_info_type)}", data, env
|
119
|
+
|
120
|
+
expect(last_response.status).to eq(200)
|
121
|
+
expect(info.reload.content).to eq(data)
|
122
|
+
|
123
|
+
expect(info.reload.type.uri).to eq(basic_info_type)
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should create unless exists' do
|
128
|
+
TentD::Model::ProfileInfo.all.destroy
|
129
|
+
|
130
|
+
data = {
|
131
|
+
"name" => "John Doe"
|
132
|
+
}
|
133
|
+
|
134
|
+
expect(lambda {
|
135
|
+
json_put "/profile/#{url_encode_type(basic_info_type)}", data, env
|
136
|
+
}).to change(TentD::Model::ProfileInfo, :count).by(1)
|
137
|
+
|
138
|
+
info = TentD::Model::ProfileInfo.last
|
139
|
+
expect(last_response.status).to eq(200)
|
140
|
+
expect(info.content).to eq(data)
|
141
|
+
expect(info.type.version).to eq('0.1.0')
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when all info types authorized' do
|
146
|
+
let(:authorized_info_types) { ['all'] }
|
147
|
+
|
148
|
+
context '', &can_update_basic_info_type
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'when specific info types authorized' do
|
152
|
+
context 'when :type_url authorized info type' do
|
153
|
+
let(:authorized_info_types) { [basic_info_type] }
|
154
|
+
|
155
|
+
context '', &can_update_basic_info_type
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'when :type_url not authoried info type' do
|
159
|
+
it 'should return 403' do
|
160
|
+
json_put "/profile/#{url_encode_type(basic_info_type)}", params, env
|
161
|
+
expect(last_response.status).to eq(403)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'when not authorized' do
|
168
|
+
it 'should return 403' do
|
169
|
+
json_put "/profile/#{url_encode_type(basic_info_type)}", params, env
|
170
|
+
expect(last_response.status).to eq(403)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'PATCH /profile' do
|
176
|
+
before { env['current_auth'] = app_authorization }
|
177
|
+
|
178
|
+
def diff_encode_type(type)
|
179
|
+
type.gsub(/~/, '~0').gsub(/\//, '~1')
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'when authorized' do
|
183
|
+
let(:authorized_scopes) { [:write_profile] }
|
184
|
+
|
185
|
+
can_update_basic_info_type = proc do
|
186
|
+
it 'should update basic info with diff' do
|
187
|
+
TentD::Model::ProfileInfo.all.destroy
|
188
|
+
|
189
|
+
info = create_info(basic_info_type, basic_info_content, :public => false)
|
190
|
+
|
191
|
+
diff = [
|
192
|
+
{ "add" => "#{diff_encode_type(basic_info_type)}/city", "value" => "New York" },
|
193
|
+
{ "remove" => "#{diff_encode_type(basic_info_type)}/age" },
|
194
|
+
{ "replace" => "#{diff_encode_type(basic_info_type)}/name", "value" => "Alex Smith" }
|
195
|
+
]
|
196
|
+
|
197
|
+
expected_data = {
|
198
|
+
"city" => "New York",
|
199
|
+
"name" => "Alex Smith",
|
200
|
+
}
|
201
|
+
|
202
|
+
json_patch "/profile", diff, env
|
203
|
+
|
204
|
+
expect(last_response.status).to eq(200)
|
205
|
+
expect(info.reload.content).to eq(expected_data)
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should return 422 if diff tests fail' do
|
209
|
+
TentD::Model::ProfileInfo.all.destroy
|
210
|
+
|
211
|
+
info = create_info(basic_info_type, basic_info_content, :public => false)
|
212
|
+
|
213
|
+
diff = [
|
214
|
+
{ "add" => "#{diff_encode_type(basic_info_type)}/city", "value" => "New York" },
|
215
|
+
{ "remove" => "#{diff_encode_type(basic_info_type)}/age" },
|
216
|
+
{ "replace" => "#{diff_encode_type(basic_info_type)}/name", "value" => "Alex Smith" },
|
217
|
+
{ "test" => "#{diff_encode_type(basic_info_type)}/age", "value" => 40 },
|
218
|
+
]
|
219
|
+
|
220
|
+
expected_data = info.content
|
221
|
+
|
222
|
+
json_patch "/profile", diff, env
|
223
|
+
|
224
|
+
expect(last_response.status).to eq(422)
|
225
|
+
expect(info.reload.content).to eq(expected_data)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'when all info types authorized' do
|
230
|
+
let(:authorized_info_types) { ['all'] }
|
231
|
+
|
232
|
+
context '', &can_update_basic_info_type
|
233
|
+
|
234
|
+
it 'should update any info' do
|
235
|
+
TentD::Model::ProfileInfo.all.destroy
|
236
|
+
|
237
|
+
info = create_info(basic_info_type, basic_info_content, :public => false)
|
238
|
+
|
239
|
+
diff = [
|
240
|
+
{ "add" => "#{diff_encode_type(basic_info_type)}/city", "value" => "New York" },
|
241
|
+
{ "remove" => "#{diff_encode_type(basic_info_type)}/age" },
|
242
|
+
{ "replace" => "#{diff_encode_type(basic_info_type)}/name", "value" => "Alex Smith" },
|
243
|
+
{ "add" => "#{diff_encode_type(work_history_type)}/employers", "value" => ["Foo Corp"] },
|
244
|
+
{ "move" => "#{diff_encode_type(basic_info_type)}/name", "to" => "#{diff_encode_type(work_history_type)}/name" },
|
245
|
+
{ "add" => "#{diff_encode_type(work_history_type)}/employers/1", "value" => "Bar Corp" },
|
246
|
+
{ "add" => "#{diff_encode_type(work_history_type)}/city", "value" => "London" }
|
247
|
+
]
|
248
|
+
|
249
|
+
expected_basic_data = {
|
250
|
+
"city" => "New York",
|
251
|
+
}
|
252
|
+
|
253
|
+
expected_work_data = {
|
254
|
+
"name" => "Alex Smith",
|
255
|
+
"employers" => ["Foo Corp", "Bar Corp"],
|
256
|
+
"city" => "London",
|
257
|
+
}
|
258
|
+
|
259
|
+
expect(lambda {
|
260
|
+
json_patch "/profile", diff, env
|
261
|
+
}).to change(TentD::Model::ProfileInfo, :count).by(1)
|
262
|
+
|
263
|
+
expect(last_response.status).to eq(200)
|
264
|
+
expect(info.reload.content).to eq(expected_basic_data)
|
265
|
+
|
266
|
+
work_info = TentD::Model::ProfileInfo.last
|
267
|
+
expect(work_info.content).to eq(expected_work_data)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'when specific info types authorized' do
|
272
|
+
let(:authorized_info_types) { [basic_info_type] }
|
273
|
+
|
274
|
+
context '', &can_update_basic_info_type
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
context 'when not authorized' do
|
279
|
+
it 'should return 403' do
|
280
|
+
json_patch '/profile', params, env
|
281
|
+
expect(last_response.status).to eq(403)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TentD::API::Router do
|
4
|
+
class TestMiddleware < TentD::API::Middleware
|
5
|
+
def action(env)
|
6
|
+
env['response'] = { 'params' => env['params'] }
|
7
|
+
env
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class TestMiddlewarePrematureResponse < TentD::API::Middleware
|
12
|
+
def action(env)
|
13
|
+
[200, { 'Content-Type' => 'text/plain' }, 'Premature-Response']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class TestMountedApp
|
18
|
+
include TentD::API::Router
|
19
|
+
|
20
|
+
get '/chunky/:bacon' do |b|
|
21
|
+
b.use TestMiddleware
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class PrefixMountedApp
|
26
|
+
def initialize(app)
|
27
|
+
@app = app
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env)
|
31
|
+
myprefix = '/prefix'
|
32
|
+
|
33
|
+
if env['PATH_INFO'].start_with?(myprefix)
|
34
|
+
env['SCRIPT_NAME'] = env['SCRIPT_NAME'][0..-2] if env['SCRIPT_NAME'].end_with?('/') # strip trailing slash
|
35
|
+
env['SCRIPT_NAME'] += myprefix
|
36
|
+
|
37
|
+
env['PATH_INFO'].sub! myprefix, ''
|
38
|
+
@app.call(env)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class TestApp
|
44
|
+
include TentD::API::Router
|
45
|
+
|
46
|
+
get '/foo/:bar' do |b|
|
47
|
+
b.use TestMiddleware
|
48
|
+
end
|
49
|
+
|
50
|
+
get '/premature/response' do |b|
|
51
|
+
b.use TestMiddlewarePrematureResponse
|
52
|
+
b.use TestMiddleware
|
53
|
+
end
|
54
|
+
|
55
|
+
post %r{^/foo/([^/]+)/bar} do |b|
|
56
|
+
b.use TestMiddleware
|
57
|
+
end
|
58
|
+
|
59
|
+
mount TestMountedApp
|
60
|
+
end
|
61
|
+
|
62
|
+
def app
|
63
|
+
TestApp.new
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:env) { { 'authorized_scopes' => [] } }
|
67
|
+
|
68
|
+
context "as a mounted app with a prefix" do
|
69
|
+
let(:app) { PrefixMountedApp.new(TestApp.new) }
|
70
|
+
|
71
|
+
it "still matches the path name" do
|
72
|
+
json_get '/prefix/foo/baz', nil, env
|
73
|
+
expect(last_response.status).to eq(200)
|
74
|
+
expect(JSON.parse(last_response.body)['params']['bar']).to eq('baz')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should extract params" do
|
79
|
+
json_get '/foo/baz', nil, env
|
80
|
+
expect(last_response.status).to eq(200)
|
81
|
+
expect(JSON.parse(last_response.body)['params']['bar']).to eq('baz')
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should merge both sets of params" do
|
85
|
+
json_post '/foo/baz/bar?chunky=bacon', nil, env
|
86
|
+
expect(last_response.status).to eq(200)
|
87
|
+
actual_body = JSON.parse(last_response.body)
|
88
|
+
expect(actual_body['params']['chunky']).to eq('bacon')
|
89
|
+
expect(actual_body['params']['captures']).to include('baz')
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should work with mount" do
|
93
|
+
json_get '/chunky/crunch', nil, env
|
94
|
+
expect(last_response.status).to eq(200)
|
95
|
+
expect(JSON.parse(last_response.body)['params']['bacon']).to eq('crunch')
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should allow middleware to prematurely respond" do
|
99
|
+
json_get '/premature/response', nil, env
|
100
|
+
expect(last_response.body).to eq('Premature-Response')
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TentD::Model::AppAuthorization do
|
4
|
+
let(:app_authorization) { Fabricate(:app_authorization, :app => Fabricate(:app)) }
|
5
|
+
|
6
|
+
describe '.follow_url' do
|
7
|
+
it 'should find app authorization with follow_ui scope and follow_url' do
|
8
|
+
Fabricate(:app_authorization, :app => Fabricate(:app), :scopes => %w{ follow_ui }, :follow_url => 'https://follow.example.org/awesome-ui')
|
9
|
+
app_auth = Fabricate(:app_authorization, :app => Fabricate(:app), :scopes => %w{ read_posts follow_ui write_posts }, :follow_url => 'https://follow.example.com')
|
10
|
+
entity = 'https://johndoe.example.org'
|
11
|
+
|
12
|
+
follow_url = described_class.follow_url(entity)
|
13
|
+
expect(follow_url).to eq("#{app_auth.follow_url}?entity=#{URI.encode_www_form_component(entity)}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#as_json' do
|
18
|
+
let(:app_attributes) do
|
19
|
+
{
|
20
|
+
:id => app_authorization.public_id,
|
21
|
+
:post_types => app_authorization.post_types,
|
22
|
+
:profile_info_types => app_authorization.profile_info_types,
|
23
|
+
:scopes => app_authorization.scopes,
|
24
|
+
:notification_url => app_authorization.notification_url,
|
25
|
+
:created_at => app_authorization.created_at.to_time.to_i,
|
26
|
+
:updated_at => app_authorization.updated_at.to_time.to_i
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with options[:app]' do
|
31
|
+
let(:options) { { :app => true } }
|
32
|
+
|
33
|
+
it 'should return everything except mac stuff' do
|
34
|
+
expect(app_authorization.as_json(options)).to eq(app_attributes)
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'and options[:authorization_token]' do
|
38
|
+
before { options[:authorization_token] = true }
|
39
|
+
it 'should return token code' do
|
40
|
+
expect(app_authorization.as_json(options)).to eq(app_attributes.merge(
|
41
|
+
:token_code => app_authorization.token_code
|
42
|
+
))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'and options[:mac]' do
|
47
|
+
before { options[:mac] = true }
|
48
|
+
|
49
|
+
it 'should return mac stuff' do
|
50
|
+
expect(app_authorization.as_json(options)).to eq(app_attributes.merge(
|
51
|
+
:mac_key_id => app_authorization.mac_key_id,
|
52
|
+
:mac_key => app_authorization.mac_key,
|
53
|
+
:mac_algorithm => app_authorization.mac_algorithm
|
54
|
+
))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TentD::Model::App do
|
4
|
+
let(:app) { Fabricate(:app) }
|
5
|
+
|
6
|
+
describe '#as_json' do
|
7
|
+
let(:public_attributes) do
|
8
|
+
{
|
9
|
+
:id => app.public_id,
|
10
|
+
:name => app.name,
|
11
|
+
:description => app.description,
|
12
|
+
:url => app.url,
|
13
|
+
:icon => app.icon,
|
14
|
+
:redirect_uris => app.redirect_uris,
|
15
|
+
:scopes => app.scopes,
|
16
|
+
:authorizations => []
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'without options' do
|
21
|
+
it 'should return public_attributes' do
|
22
|
+
expect(app.as_json).to eq(public_attributes)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
with_mac_keys = proc do
|
27
|
+
it 'should return mac keys' do
|
28
|
+
expect(app.as_json(options)).to eq(public_attributes.merge(
|
29
|
+
:mac_key_id => app.mac_key_id,
|
30
|
+
:mac_key => app.mac_key,
|
31
|
+
:mac_algorithm => app.mac_algorithm
|
32
|
+
))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with options[:mac]' do
|
37
|
+
let(:options) { { :mac => true } }
|
38
|
+
context &with_mac_keys
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with options[:exclude]' do
|
42
|
+
it 'should excude specified keys' do
|
43
|
+
attribtues = public_attributes
|
44
|
+
attribtues.delete(:id)
|
45
|
+
expect(app.as_json(:exclude => [:id])).to eq(attribtues)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with options[:app]' do
|
50
|
+
let!(:app) { Fabricate(:app) }
|
51
|
+
let!(:authorization) { Fabricate(:app_authorization, :app => app) }
|
52
|
+
|
53
|
+
it 'should return authorizations' do
|
54
|
+
options = { :app => true }
|
55
|
+
expect(app.as_json(options)).to eq(public_attributes.merge(
|
56
|
+
:authorizations => [authorization.as_json(options)],
|
57
|
+
:created_at => app.created_at.to_time.to_i,
|
58
|
+
:updated_at => app.updated_at.to_time.to_i
|
59
|
+
))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|