boxr 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env.example +3 -3
- data/.gitignore +1 -0
- data/README.md +3 -0
- data/lib/boxr/auth.rb +22 -9
- data/lib/boxr/client.rb +2 -0
- data/lib/boxr/version.rb +1 -1
- data/spec/boxr/auth_spec.rb +31 -0
- data/spec/boxr/collaborations_spec.rb +1 -1
- data/spec/boxr_spec.rb +4 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2229eb1062b34eabf5e7040caf0a2c497caa7d2ef13c75f896eb76e1e7c25fea
|
4
|
+
data.tar.gz: 4404394473173cfa99b4f5b22af110fa2dbd1f9018262fa3b4c48c49f51ba99a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 958241267042bcdcbd94247873beefe73afbd43da4860047411c5891fcc25cd56555b719b2f760d9e949c14e6a88c4a90e7658b4c12cc11b4a592c367f02ddf0
|
7
|
+
data.tar.gz: 8d6c582d64c0be4ca4da7cc87f629b2735d90b4640eb2ee154b9cf32597e2f3fa9f65c1fe2c544c075d671d1d0a8d89ac7eabc42cc86fc69ec7d68e9487d524a
|
data/.env.example
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#1. go to https://developers.box.com,
|
1
|
+
#1. go to https://developers.box.com,
|
2
2
|
#2. find or create your Box Content API app for testing
|
3
3
|
#3. click 'Edit Application'
|
4
4
|
#4. check the boxes for 'Read and write all files and folders' and 'Manage an enterprise'
|
@@ -11,5 +11,5 @@ BOX_DEVELOPER_TOKEN={a valid developer token for your Box app}
|
|
11
11
|
BOX_CLIENT_ID={client id of your Box app}
|
12
12
|
BOX_CLIENT_SECRET={client secret of your Box app}
|
13
13
|
BOX_ENTERPRISE_ID={box enterprise id}
|
14
|
-
|
15
|
-
|
14
|
+
JWT_PRIVATE_KEY_PATH={path to your JWT private key}
|
15
|
+
JWT_PRIVATE_KEY_PASSWORD={JWT private key password}
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
# Boxr
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/boxr.svg)](https://badge.fury.io/rb/boxr)
|
4
|
+
|
2
5
|
Boxr is a Ruby client library for the Box V2 Content API. Box employees affectionately refer to one another as Boxers, hence the name of this gem.
|
3
6
|
|
4
7
|
The purpose of this gem is to provide a clear, efficient, and intentional method of interacting with the Box Content API. As with any SDK that wraps a REST API, it is important to fully understand the Box Content API at the REST endpoint level. You are strongly encouraged to read through the Box documentation located [here](https://box-content.readme.io/).
|
data/lib/boxr/auth.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Boxr
|
2
2
|
|
3
3
|
JWT_GRANT_TYPE="urn:ietf:params:oauth:grant-type:jwt-bearer"
|
4
|
+
TOKEN_EXCHANGE_TOKEN_TYPE="urn:ietf:params:oauth:token-type:access_token"
|
5
|
+
TOKEN_EXCHANGE_GRANT_TYPE="urn:ietf:params:oauth:grant-type:token-exchange"
|
4
6
|
|
5
7
|
def self.oauth_url(state, host: "app.box.com", response_type: "code", scope: nil, folder_id: nil, client_id: ENV['BOX_CLIENT_ID'])
|
6
8
|
template = Addressable::Template.new("https://{host}/api/oauth2/authorize{?query*}")
|
@@ -8,13 +10,13 @@ module Boxr
|
|
8
10
|
query = {"response_type" => "#{response_type}", "state" => "#{state}", "client_id" => "#{client_id}"}
|
9
11
|
query["scope"] = "#{scope}" unless scope.nil?
|
10
12
|
query["folder_id"] = "#{folder_id}" unless folder_id.nil?
|
11
|
-
|
13
|
+
|
12
14
|
uri = template.expand({"host" => "#{host}", "query" => query})
|
13
15
|
uri
|
14
16
|
end
|
15
17
|
|
16
18
|
def self.get_tokens(code=nil, grant_type: "authorization_code", assertion: nil, scope: nil, username: nil, client_id: ENV['BOX_CLIENT_ID'], client_secret: ENV['BOX_CLIENT_SECRET'])
|
17
|
-
uri =
|
19
|
+
uri = Boxr::Client::AUTH_URI
|
18
20
|
body = "grant_type=#{grant_type}&client_id=#{client_id}&client_secret=#{client_secret}"
|
19
21
|
body = body + "&code=#{code}" unless code.nil?
|
20
22
|
body = body + "&scope=#{scope}" unless scope.nil?
|
@@ -25,7 +27,7 @@ module Boxr
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def self.get_enterprise_token(private_key: ENV['JWT_PRIVATE_KEY'], private_key_password: ENV['JWT_PRIVATE_KEY_PASSWORD'],
|
28
|
-
public_key_id: ENV['JWT_PUBLIC_KEY_ID'], enterprise_id: ENV['BOX_ENTERPRISE_ID'],
|
30
|
+
public_key_id: ENV['JWT_PUBLIC_KEY_ID'], enterprise_id: ENV['BOX_ENTERPRISE_ID'],
|
29
31
|
client_id: ENV['BOX_CLIENT_ID'], client_secret: ENV['BOX_CLIENT_SECRET'])
|
30
32
|
unlocked_private_key = unlock_key(private_key, private_key_password)
|
31
33
|
assertion = jwt_assertion(unlocked_private_key, client_id, enterprise_id, "enterprise", public_key_id)
|
@@ -40,19 +42,31 @@ module Boxr
|
|
40
42
|
end
|
41
43
|
|
42
44
|
def self.refresh_tokens(refresh_token, client_id: ENV['BOX_CLIENT_ID'], client_secret: ENV['BOX_CLIENT_SECRET'])
|
43
|
-
uri =
|
45
|
+
uri = Boxr::Client::AUTH_URI
|
44
46
|
body = "grant_type=refresh_token&refresh_token=#{refresh_token}&client_id=#{client_id}&client_secret=#{client_secret}"
|
45
47
|
|
46
48
|
auth_post(uri, body)
|
47
49
|
end
|
48
50
|
|
49
51
|
def self.revoke_tokens(token, client_id: ENV['BOX_CLIENT_ID'], client_secret: ENV['BOX_CLIENT_SECRET'])
|
50
|
-
uri =
|
52
|
+
uri = Boxr::Client::REVOKE_AUTH_URI
|
51
53
|
body = "client_id=#{client_id}&client_secret=#{client_secret}&token=#{token}"
|
52
54
|
|
53
55
|
auth_post(uri, body)
|
54
56
|
end
|
55
57
|
|
58
|
+
# Exchange an existing token for a lesser-scoped token
|
59
|
+
def self.exchange_token(subject_token, scope, resource_id: nil, resource_type: :file)
|
60
|
+
uri = Boxr::Client::AUTH_URI
|
61
|
+
resouce_uri = resource_type == :file ? Boxr::Client::FILES_URI : Boxr::Client::FOLDERS_URI
|
62
|
+
resource_url = "#{resouce_uri}/#{resource_id}"
|
63
|
+
|
64
|
+
body = "subject_token=#{subject_token}&subject_token_type=#{TOKEN_EXCHANGE_TOKEN_TYPE}&scope=#{scope}&grant_type=#{TOKEN_EXCHANGE_GRANT_TYPE}"
|
65
|
+
body = body + "&resource=#{resource_url}" unless resource_id.nil?
|
66
|
+
|
67
|
+
auth_post(uri, body)
|
68
|
+
end
|
69
|
+
|
56
70
|
class << self
|
57
71
|
alias :get_token :get_tokens
|
58
72
|
alias :refresh_token :refresh_tokens
|
@@ -67,14 +81,14 @@ module Boxr
|
|
67
81
|
iss: iss,
|
68
82
|
sub: sub,
|
69
83
|
box_sub_type: box_sub_type,
|
70
|
-
aud:
|
84
|
+
aud: Boxr::Client::AUTH_URI,
|
71
85
|
jti: SecureRandom.hex(64),
|
72
86
|
exp: (Time.now.utc + 10).to_i
|
73
87
|
}
|
74
88
|
|
75
89
|
additional_headers = {}
|
76
90
|
additional_headers['kid'] = public_key_id unless public_key_id.nil?
|
77
|
-
|
91
|
+
|
78
92
|
JWT.encode(payload, private_key, "RS256", additional_headers)
|
79
93
|
end
|
80
94
|
|
@@ -98,5 +112,4 @@ module Boxr
|
|
98
112
|
OpenSSL::PKey::RSA.new(private_key, private_key_password)
|
99
113
|
end
|
100
114
|
end
|
101
|
-
|
102
|
-
end
|
115
|
+
end
|
data/lib/boxr/client.rb
CHANGED
@@ -8,6 +8,8 @@ module Boxr
|
|
8
8
|
#UPLOAD_URI = "https://upload.wcheng.inside-box.net/api/2.0"
|
9
9
|
|
10
10
|
API_URI = "https://api.box.com/2.0"
|
11
|
+
AUTH_URI = "https://api.box.com/oauth2/token"
|
12
|
+
REVOKE_AUTH_URI = "https://api.box.com/oauth2/revoke"
|
11
13
|
UPLOAD_URI = "https://upload.box.com/api/2.0"
|
12
14
|
FILES_URI = "#{API_URI}/files"
|
13
15
|
FILES_UPLOAD_URI = "#{UPLOAD_URI}/files/content"
|
data/lib/boxr/version.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
#rake spec SPEC_OPTS="-e \"invokes auth operations"\"
|
4
|
+
describe 'auth operations' do
|
5
|
+
it "invokes auth operations" do
|
6
|
+
private_key = OpenSSL::PKey::RSA.new(File.read(ENV['JWT_PRIVATE_KEY_PATH']), ENV['JWT_PRIVATE_KEY_PASSWORD'])
|
7
|
+
|
8
|
+
puts "get enterprise token"
|
9
|
+
enterprise_token = Boxr::get_enterprise_token(private_key: private_key)
|
10
|
+
expect(enterprise_token).to include('access_token', 'expires_in')
|
11
|
+
|
12
|
+
puts "downgrade token"
|
13
|
+
child_token = Boxr::exchange_token(enterprise_token['access_token'], 'root_readonly')
|
14
|
+
expect(child_token).to include('access_token','expires_in')
|
15
|
+
|
16
|
+
# Currently cannot test due to user requiring
|
17
|
+
puts "get user token"
|
18
|
+
second_test_user = BOX_CLIENT.create_user("Second Test User", login: "second_test_user@#{('a'..'z').to_a.shuffle[0,10].join}.com", role: 'user', is_platform_access_only: true)
|
19
|
+
user_token = Boxr::get_user_token(second_test_user.id, private_key: private_key)
|
20
|
+
expect(user_token).to include('access_token','expires_in')
|
21
|
+
|
22
|
+
puts "revoke user token"
|
23
|
+
user_client = Boxr::Client.new(user_token['access_token'])
|
24
|
+
expect(user_client.root_folder_items).to eq []
|
25
|
+
Boxr::revoke_token(user_token['access_token'])
|
26
|
+
expect{user_client.root_folder_items}.to raise_error{Boxr::BoxrError}
|
27
|
+
|
28
|
+
puts "cleanup data"
|
29
|
+
BOX_CLIENT.delete_user(second_test_user, force: true)
|
30
|
+
end
|
31
|
+
end
|
@@ -32,6 +32,6 @@ describe 'collaborations operations' do
|
|
32
32
|
expect(pending_collaborations).to eq([])
|
33
33
|
|
34
34
|
puts "add invalid collaboration"
|
35
|
-
expect { BOX_CLIENT.add_collaboration(@test_folder, {id: @test_user.id, type: :user}, :invalid_role)}.to raise_error
|
35
|
+
expect { BOX_CLIENT.add_collaboration(@test_folder, {id: @test_user.id, type: :user}, :invalid_role)}.to raise_error{Boxr::BoxrError}
|
36
36
|
end
|
37
37
|
end
|
data/spec/boxr_spec.rb
CHANGED
@@ -10,7 +10,11 @@ describe Boxr::Client do
|
|
10
10
|
|
11
11
|
#REQUIRED BOX SETTINGS
|
12
12
|
# 1. The developer token used must have admin or co-admin priviledges
|
13
|
+
# 1.5 In the admin settings, advanced features must be enabled (perform as user and create user access tokens)
|
13
14
|
# 2. Enterprise settings must allow Admin and Co-admins to permanently delete content in Trash
|
15
|
+
# 3. In Box Admin settings, you must authorize the app.
|
16
|
+
# - Admin Console > Enterprise Settings > Apps > Custom Applications > Authorize New App. Insert you client ID (API key)
|
17
|
+
# - You may need to re-authorize the app if you're running into issues with user tokens
|
14
18
|
|
15
19
|
#follow the directions in .env.example to set up your BOX_DEVELOPER_TOKEN
|
16
20
|
#keep in mind it is only valid for 60 minutes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boxr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chad Burnette
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -209,6 +209,7 @@ files:
|
|
209
209
|
- lib/boxr/version.rb
|
210
210
|
- lib/boxr/watermarking.rb
|
211
211
|
- lib/boxr/web_links.rb
|
212
|
+
- spec/boxr/auth_spec.rb
|
212
213
|
- spec/boxr/collaborations_spec.rb
|
213
214
|
- spec/boxr/comments_spec.rb
|
214
215
|
- spec/boxr/files_spec.rb
|
@@ -247,6 +248,7 @@ signing_key:
|
|
247
248
|
specification_version: 4
|
248
249
|
summary: A Ruby client library for the Box V2 Content API.
|
249
250
|
test_files:
|
251
|
+
- spec/boxr/auth_spec.rb
|
250
252
|
- spec/boxr/collaborations_spec.rb
|
251
253
|
- spec/boxr/comments_spec.rb
|
252
254
|
- spec/boxr/files_spec.rb
|