iora-ruby-box 1.14.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.
- data/.document +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +51 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +349 -0
- data/Rakefile +32 -0
- data/VERSION +1 -0
- data/lib/ruby-box.rb +21 -0
- data/lib/ruby-box/client.rb +163 -0
- data/lib/ruby-box/collaboration.rb +19 -0
- data/lib/ruby-box/comment.rb +14 -0
- data/lib/ruby-box/discussion.rb +15 -0
- data/lib/ruby-box/event.rb +4 -0
- data/lib/ruby-box/event_response.rb +17 -0
- data/lib/ruby-box/exceptions.rb +22 -0
- data/lib/ruby-box/file.rb +96 -0
- data/lib/ruby-box/folder.rb +113 -0
- data/lib/ruby-box/item.rb +181 -0
- data/lib/ruby-box/session.rb +136 -0
- data/lib/ruby-box/shared_link.rb +10 -0
- data/lib/ruby-box/user.rb +16 -0
- data/lib/ruby-box/web_link.rb +4 -0
- data/ruby-box.gemspec +99 -0
- data/spec/client_spec.rb +64 -0
- data/spec/event_spec.rb +70 -0
- data/spec/file_spec.rb +110 -0
- data/spec/fixtures/comment_create.json +18 -0
- data/spec/fixtures/events.json +161 -0
- data/spec/fixtures/me.json +17 -0
- data/spec/fixtures/users.json +39 -0
- data/spec/folder_spec.rb +181 -0
- data/spec/helper/account.example +3 -0
- data/spec/helper/account.rb +8 -0
- data/spec/integration_spec.rb +387 -0
- data/spec/item_spec.rb +31 -0
- data/spec/me_spec.rb +20 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/users_spec.rb +24 -0
- metadata +214 -0
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'helper/account'
|
5
|
+
require 'ruby-box'
|
6
|
+
require 'webmock/rspec'
|
7
|
+
|
8
|
+
describe RubyBox::Client do
|
9
|
+
before do
|
10
|
+
@session = RubyBox::Session.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#folder' do
|
14
|
+
it "should return root folder as default behavior for paths such as ./" do
|
15
|
+
RubyBox::Client.any_instance.should_receive(:root_folder).exactly(4).times
|
16
|
+
client = RubyBox::Client.new(@session)
|
17
|
+
client.folder()
|
18
|
+
client.folder('.')
|
19
|
+
client.folder('./')
|
20
|
+
client.folder('/')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#split_path' do
|
25
|
+
it "returns the appropriate path" do
|
26
|
+
client = RubyBox::Client.new(@session)
|
27
|
+
client.split_path('foo/bar').should == ['foo', 'bar']
|
28
|
+
end
|
29
|
+
|
30
|
+
it "leading / is ignored" do
|
31
|
+
client = RubyBox::Client.new(@session)
|
32
|
+
client.split_path('/foo/bar').should == ['foo', 'bar']
|
33
|
+
end
|
34
|
+
|
35
|
+
it "trailing / is ignored" do
|
36
|
+
client = RubyBox::Client.new(@session)
|
37
|
+
client.split_path('foo/bar/').should == ['foo', 'bar']
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#create_folder' do
|
42
|
+
it 'doesnt call folder.create_folder if the folder exists' do
|
43
|
+
client = RubyBox::Client.new(@session)
|
44
|
+
mock_root_folder = mock( Object )
|
45
|
+
test_folder = mock( Object )
|
46
|
+
mock_root_folder.should_receive(:folders).and_return([test_folder])
|
47
|
+
mock_root_folder.should_not_receive(:create_subfolder)
|
48
|
+
client.should_receive(:root_folder).and_return(mock_root_folder)
|
49
|
+
result = client.create_folder( '/test0')
|
50
|
+
result.should == test_folder
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'calls folder.create_folder if the folder does not exist' do
|
54
|
+
client = RubyBox::Client.new(@session)
|
55
|
+
mock_root_folder = mock( Object )
|
56
|
+
test_folder = mock( Object )
|
57
|
+
mock_root_folder.should_receive(:folders).and_return([])
|
58
|
+
mock_root_folder.should_receive(:create_subfolder).and_return(test_folder)
|
59
|
+
client.should_receive(:root_folder).and_return(mock_root_folder)
|
60
|
+
result = client.create_folder( '/test0')
|
61
|
+
result.should == test_folder
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/spec/event_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
require 'ruby-box'
|
4
|
+
require 'webmock/rspec'
|
5
|
+
|
6
|
+
describe RubyBox::EventResponse do
|
7
|
+
before do
|
8
|
+
@session = RubyBox::Session.new
|
9
|
+
@client = RubyBox::Client.new(@session)
|
10
|
+
@events_json = File.read 'spec/fixtures/events.json'
|
11
|
+
@events = JSON.load @events_json
|
12
|
+
stub_request(:get, /#{RubyBox::API_URL}\/events.*/).to_return(body: @events_json, :status => 200)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns an EventResponse with a chunk_size and next_stream_position' do
|
16
|
+
eresp = @client.event_response
|
17
|
+
eresp.instance_of?(RubyBox::EventResponse).should be_true
|
18
|
+
eresp.events.instance_of?(Array).should be_true
|
19
|
+
eresp.chunk_size.should eq(@events['chunk_size'])
|
20
|
+
eresp.events.length.should eq(@events['chunk_size'])
|
21
|
+
eresp.next_stream_position.should eq(@events['next_stream_position'])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not try to reload_meta since has_mini_format? is false" do
|
25
|
+
# request is called once when reload_meta is automatically executed.
|
26
|
+
RubyBox::Session.any_instance.should_not_receive(:request)
|
27
|
+
response = @client.event_response
|
28
|
+
event = response.events.first
|
29
|
+
event.missing_key
|
30
|
+
end
|
31
|
+
|
32
|
+
it '#fmt_events_args should return a properly formatted URL' do
|
33
|
+
@client.send(:fmt_events_args, 0, :all, 100).should eql("stream_position=0&stream_type=all&limit=100")
|
34
|
+
@client.send(:fmt_events_args, 'now', :changes, 55).should eql("stream_position=now&stream_type=changes&limit=55")
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#event_response' do
|
38
|
+
before do
|
39
|
+
@response = @client.event_response
|
40
|
+
@event = @response.events.first
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should return Event objects in the event response' do
|
44
|
+
@event.instance_of?(RubyBox::Event).should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should return an #event_id' do
|
48
|
+
@event.event_id.should eq(@events['entries'][0]['event_id'])
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should return a User for #created_by' do
|
52
|
+
@event.created_by.instance_of?(RubyBox::User).should be_true
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should return an #event_type' do
|
56
|
+
@event.event_type.should eq(@events['entries'][0]['event_type'])
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return a #session_id' do
|
60
|
+
@event.session_id.should eq(@events['entries'][0]['session_id'])
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should return an instantiated #source' do
|
64
|
+
@event.source.instance_of?(RubyBox::Folder).should be_true
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
data/spec/file_spec.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'helper/account'
|
5
|
+
require 'ruby-box'
|
6
|
+
require 'webmock/rspec'
|
7
|
+
|
8
|
+
describe RubyBox::File do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@session = RubyBox::Session.new
|
12
|
+
@full_file = JSON.parse('{ "type": "file", "id": "5000948880", "sequence_id": "3", "etag": "3", "sha1": "134b65991ed521fcfe4724b7d814ab8ded5185dc", "name": "tigers.jpeg", "description": "a picture of tigers", "size": 629644, "path_collection": { "total_count": 2, "entries": [ { "type": "folder", "id": "0", "sequence_id": null, "etag": null, "name": "All Files" }, { "type": "folder", "id": "11446498", "sequence_id": "1", "etag": "1", "name": "Pictures" } ] }, "created_at": "2012-12-12T10:55:30-08:00", "modified_at": "2012-12-12T11:04:26-08:00", "trashed_at": null, "purged_at": null, "content_created_at": "2013-02-04T16:57:52-08:00", "content_modified_at": "2013-02-04T16:57:52-08:00", "created_by": { "type": "user", "id": "17738362", "name": "sean rose", "login": "sean@box.com" }, "modified_by": { "type": "user", "id": "17738362", "name": "sean rose", "login": "sean@box.com" }, "owned_by": { "type": "user", "id": "17738362", "name": "sean rose", "login": "sean@box.com" }, "shared_link": { "url": "https://www.box.com/s/rh935iit6ewrmw0unyul", "download_url": "https://www.box.com/shared/static/rh935iit6ewrmw0unyul.jpeg", "vanity_url": null, "is_password_enabled": false, "unshared_at": null, "download_count": 0, "preview_count": 0, "access": "open", "permissions": { "can_download": true, "can_preview": true } }, "parent": { "type": "folder", "id": "11446498", "sequence_id": "1", "etag": "1", "name": "Pictures" }, "item_status": "active"}')
|
13
|
+
@mini_file = JSON.parse('{ "sequence_id": "0", "type": "file", "id": "2631999573", "name":"IMG_1312.JPG"}')
|
14
|
+
@comments = JSON.parse('{ "total_count": 1, "entries": [ { "type": "comment", "id": "191969", "is_reply_comment": false, "message": "These tigers are cool!", "created_by": { "type": "user", "id": "17738362", "name": "sean rose", "login": "sean@box.com" }, "created_at": "2012-12-12T11:25:01-08:00", "item": { "id": "5000948880", "type": "file" }, "modified_at": "2012-12-12T11:25:01-08:00" } ]}')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should use missing_method to expose files fields" do
|
18
|
+
file = RubyBox::File.new(@session, @mini_file)
|
19
|
+
file.id.should == '2631999573'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should load all meta information if reload_meta is called" do
|
23
|
+
# request is called once when reload_meta is automatically executed.
|
24
|
+
RubyBox::Session.any_instance.should_receive(:request).once.and_return(@full_file)
|
25
|
+
session = RubyBox::Session.new
|
26
|
+
|
27
|
+
file = RubyBox::File.new(session, @mini_file)
|
28
|
+
file.size.should == 629644
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#parent' do
|
32
|
+
it 'should return parent folder' do
|
33
|
+
session = RubyBox::Session.new
|
34
|
+
file = RubyBox::File.new(session, @full_file)
|
35
|
+
file.parent.name.should == 'Pictures'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should reload_meta data if necessary before loading parent' do
|
39
|
+
RubyBox::Session.any_instance.stub(:request).and_return(@full_file)
|
40
|
+
session = RubyBox::Session.new
|
41
|
+
file = RubyBox::File.new(session, @mini_file)
|
42
|
+
file.parent.name.should == 'Pictures'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#update' do
|
47
|
+
it 'should update files raw_item hash if name or description changed' do
|
48
|
+
RubyBox::Session.any_instance.stub(:request).and_return(@full_file)
|
49
|
+
session = RubyBox::Session.new
|
50
|
+
file = RubyBox::File.new(session, @mini_file)
|
51
|
+
file.name = 'Funky Monkey.jpg'
|
52
|
+
file.description = 'a new description'
|
53
|
+
file.name.should == 'Funky Monkey.jpg'
|
54
|
+
file.description.should == 'a new description'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should not update files raw_item hash for keys not in update_fields' do
|
58
|
+
RubyBox::Session.any_instance.stub(:request).and_return(@full_file)
|
59
|
+
session = RubyBox::Session.new
|
60
|
+
file = RubyBox::File.new(session, @mini_file)
|
61
|
+
file.id = '000'
|
62
|
+
file.id.should == '2631999573'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should make request with appropriate update hash when update called' do
|
66
|
+
RubyBox::Session.any_instance.stub(:request) do |uri, request|
|
67
|
+
data = JSON.parse(request.body)
|
68
|
+
data['description'].should == 'a new description'
|
69
|
+
end
|
70
|
+
session = RubyBox::Session.new
|
71
|
+
file = RubyBox::File.new(session, @full_file)
|
72
|
+
file.description = 'a new description'
|
73
|
+
file.update
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#put_data' do
|
78
|
+
it "should load full meta information if etag not present" do
|
79
|
+
RubyBox::Session.any_instance.should_receive(:request).twice.and_return(@full_file)
|
80
|
+
session = RubyBox::Session.new
|
81
|
+
file = RubyBox::File.new(session, @mini_file)
|
82
|
+
file.stub(:prepare_upload).and_return('fake data')
|
83
|
+
file.update_content('data')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#comments' do
|
88
|
+
it 'should return an array of comment objects' do
|
89
|
+
RubyBox::Session.any_instance.stub(:request).and_return(@comments)
|
90
|
+
session = RubyBox::Session.new
|
91
|
+
file = RubyBox::File.new(session, @mini_file)
|
92
|
+
file.comments.first.message.should == 'These tigers are cool!'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#create_comment' do
|
97
|
+
it 'calls the /comments resource with the appropriate post body' do
|
98
|
+
stub_request(:post, "https://api.box.com/2.0/comments")
|
99
|
+
.to_return(:body => File.read('./spec/fixtures/comment_create.json'), :status => 200)
|
100
|
+
|
101
|
+
session = RubyBox::Session.new
|
102
|
+
file = RubyBox::File.new(session, @mini_file)
|
103
|
+
comment = file.create_comment('Hello world!')
|
104
|
+
|
105
|
+
# note that this value comes from the fixture.
|
106
|
+
comment.message.should == 'These tigers are cool!'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
{
|
2
|
+
"type": "comment",
|
3
|
+
"id": "191969",
|
4
|
+
"is_reply_comment": false,
|
5
|
+
"message": "These tigers are cool!",
|
6
|
+
"created_by": {
|
7
|
+
"type": "user",
|
8
|
+
"id": "17738362",
|
9
|
+
"name": "sean rose",
|
10
|
+
"login": "sean@box.com"
|
11
|
+
},
|
12
|
+
"created_at": "2012-12-12T11:25:01-08:00",
|
13
|
+
"item": {
|
14
|
+
"id": "5000948880",
|
15
|
+
"type": "file"
|
16
|
+
},
|
17
|
+
"modified_at": "2012-12-12T11:25:01-08:00"
|
18
|
+
}
|
@@ -0,0 +1,161 @@
|
|
1
|
+
{
|
2
|
+
"chunk_size": 3,
|
3
|
+
"next_stream_position": 1366038336000,
|
4
|
+
"entries": [
|
5
|
+
{
|
6
|
+
"type": "event",
|
7
|
+
"event_id": "dd4cba8afb2acb3cc0ecc43c81e565e78886494b",
|
8
|
+
"created_by": {
|
9
|
+
"type": "user",
|
10
|
+
"id": "000000000",
|
11
|
+
"name": "Example User",
|
12
|
+
"login": "test@example.com"
|
13
|
+
},
|
14
|
+
"created_at": "2013-04-12T13:53:52-07:00",
|
15
|
+
"recorded_at": "2013-04-12T13:53:52-07:00",
|
16
|
+
"event_type": "ITEM_CREATE",
|
17
|
+
"session_id": "d223c5ba4f4eb1d0b4fb55a",
|
18
|
+
"source": {
|
19
|
+
"type": "folder",
|
20
|
+
"id": "805142927",
|
21
|
+
"sequence_id": "0",
|
22
|
+
"etag": "0",
|
23
|
+
"name": "Test Folder",
|
24
|
+
"created_at": "2013-04-12T13:53:52-07:00",
|
25
|
+
"modified_at": "2013-04-12T13:53:52-07:00",
|
26
|
+
"description": "",
|
27
|
+
"size": 0,
|
28
|
+
"path_collection": {
|
29
|
+
"total_count": 1,
|
30
|
+
"entries": [
|
31
|
+
{
|
32
|
+
"type": "folder",
|
33
|
+
"id": "0",
|
34
|
+
"sequence_id": null,
|
35
|
+
"etag": null,
|
36
|
+
"name": "All Files"
|
37
|
+
}
|
38
|
+
]
|
39
|
+
},
|
40
|
+
"created_by": {
|
41
|
+
"type": "user",
|
42
|
+
"id": "000000000",
|
43
|
+
"name": "Example User",
|
44
|
+
"login": "test@example.com"
|
45
|
+
},
|
46
|
+
"modified_by": {
|
47
|
+
"type": "user",
|
48
|
+
"id": "000000000",
|
49
|
+
"name": "Example User",
|
50
|
+
"login": "test@example.com"
|
51
|
+
},
|
52
|
+
"trashed_at": null,
|
53
|
+
"purged_at": null,
|
54
|
+
"content_created_at": "2013-04-12T13:53:52-07:00",
|
55
|
+
"content_modified_at": "2013-04-12T13:53:52-07:00",
|
56
|
+
"owned_by": {
|
57
|
+
"type": "user",
|
58
|
+
"id": "000000000",
|
59
|
+
"name": "Example User",
|
60
|
+
"login": "test@example.com"
|
61
|
+
},
|
62
|
+
"shared_link": null,
|
63
|
+
"folder_upload_email": null,
|
64
|
+
"parent": {
|
65
|
+
"type": "folder",
|
66
|
+
"id": "0",
|
67
|
+
"sequence_id": null,
|
68
|
+
"etag": null,
|
69
|
+
"name": "All Files"
|
70
|
+
},
|
71
|
+
"item_status": "active",
|
72
|
+
"synced": false
|
73
|
+
}
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"type": "event",
|
77
|
+
"event_id": "dd4cba8afb2acb3cc0ecc43c81e565e78886494c",
|
78
|
+
"created_by": {
|
79
|
+
"type": "user",
|
80
|
+
"id": "000000000",
|
81
|
+
"name": "Example User",
|
82
|
+
"login": "test@example.com"
|
83
|
+
},
|
84
|
+
"created_at": "2013-04-12T13:54:25-07:00",
|
85
|
+
"recorded_at": "2013-04-12T13:54:26-07:00",
|
86
|
+
"event_type": "ITEM_RENAME",
|
87
|
+
"session_id": "d223c5ba4f4eb1d0b4fb55a",
|
88
|
+
"source": {
|
89
|
+
"type": "folder",
|
90
|
+
"id": "805142927",
|
91
|
+
"sequence_id": "1",
|
92
|
+
"etag": "1",
|
93
|
+
"name": "Test Folder",
|
94
|
+
"created_at": "2013-04-12T13:53:52-07:00",
|
95
|
+
"modified_at": "2013-04-12T13:54:25-07:00",
|
96
|
+
"description": "Project: Test",
|
97
|
+
"size": 0,
|
98
|
+
"path_collection": {
|
99
|
+
"total_count": 1,
|
100
|
+
"entries": [
|
101
|
+
{
|
102
|
+
"type": "folder",
|
103
|
+
"id": "0",
|
104
|
+
"sequence_id": null,
|
105
|
+
"etag": null,
|
106
|
+
"name": "All Files"
|
107
|
+
}
|
108
|
+
]
|
109
|
+
},
|
110
|
+
"created_by": {
|
111
|
+
"type": "user",
|
112
|
+
"id": "000000000",
|
113
|
+
"name": "Example User",
|
114
|
+
"login": "test@example.com"
|
115
|
+
},
|
116
|
+
"modified_by": {
|
117
|
+
"type": "user",
|
118
|
+
"id": "000000000",
|
119
|
+
"name": "Example User",
|
120
|
+
"login": "test@example.com"
|
121
|
+
},
|
122
|
+
"trashed_at": null,
|
123
|
+
"purged_at": null,
|
124
|
+
"content_created_at": "2013-04-12T13:53:52-07:00",
|
125
|
+
"content_modified_at": "2013-04-12T13:54:25-07:00",
|
126
|
+
"owned_by": {
|
127
|
+
"type": "user",
|
128
|
+
"id": "000000000",
|
129
|
+
"name": "Example User",
|
130
|
+
"login": "test@example.com"
|
131
|
+
},
|
132
|
+
"shared_link": null,
|
133
|
+
"folder_upload_email": null,
|
134
|
+
"parent": {
|
135
|
+
"type": "folder",
|
136
|
+
"id": "0",
|
137
|
+
"sequence_id": null,
|
138
|
+
"etag": null,
|
139
|
+
"name": "All Files"
|
140
|
+
},
|
141
|
+
"item_status": "active",
|
142
|
+
"synced": false
|
143
|
+
}
|
144
|
+
},
|
145
|
+
{
|
146
|
+
"type": "event",
|
147
|
+
"event_id": "dd4cba8afb2acb3cc0ecc43c81e565e78886494d",
|
148
|
+
"created_by": {
|
149
|
+
"type": "user",
|
150
|
+
"id": "000000000",
|
151
|
+
"name": "Example User",
|
152
|
+
"login": "test@example.com"
|
153
|
+
},
|
154
|
+
"created_at": "2013-04-12T14:02:06-07:00",
|
155
|
+
"recorded_at": "2013-04-12T14:02:06-07:00",
|
156
|
+
"event_type": "TAG_ITEM_CREATE",
|
157
|
+
"session_id": "d223c5ba4f4eb1d0b4fb55a",
|
158
|
+
"source": null
|
159
|
+
}
|
160
|
+
]
|
161
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"type": "user",
|
3
|
+
"id": "10000000",
|
4
|
+
"name": "Test User",
|
5
|
+
"login": "test@example.com",
|
6
|
+
"created_at": "2013-05-01T11:26:07-05:00",
|
7
|
+
"modified_at": "2013-05-01T11:26:07-05:00",
|
8
|
+
"language": "en",
|
9
|
+
"space_amount": 2400000000,
|
10
|
+
"space_used": 2000000,
|
11
|
+
"max_upload_size": 200000000,
|
12
|
+
"status": "active",
|
13
|
+
"job_title": "Unit Tester",
|
14
|
+
"phone": "5555555555",
|
15
|
+
"address": "600 Unit Test Way",
|
16
|
+
"avatar_url": "https://www.box.com/api/avatar/large/10000000"
|
17
|
+
}
|