globus_client 0.2.0 → 0.3.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 +4 -4
- data/Gemfile.lock +10 -7
- data/README.md +24 -3
- data/api_test.rb +37 -0
- data/lib/globus/client/endpoint.rb +85 -42
- data/lib/globus/client/identity.rb +7 -0
- data/lib/globus/client/version.rb +1 -1
- data/lib/globus/client.rb +22 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a4c2d5c57d5c7439a64bf4a0c9da297422987a026ff9eafdb38722df11de72c
|
4
|
+
data.tar.gz: 48b723cfdcad41ccd033dcb57ea2e09ad1da8ec139f7a98cf36a6c264565898c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc74c6a8123ff04756bffcb06e6f0765eba0aaa18c634dd1d4481767392f320aa57bf0dec54904b92d92d88c6fa239dff417fec6c372f0b5af7293f61dc00dcd
|
7
|
+
data.tar.gz: 1b0b02bcbfe3964fb4f8e526af347403654a93441ddebe8fb3ea3ea8bd5cde326a3327c026114a2309f6650d029f0c4c3484bd8a831a2b55867b1d67436fc5f4
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
globus_client (0.1
|
4
|
+
globus_client (0.2.1)
|
5
5
|
activesupport (>= 4.2, < 8)
|
6
6
|
faraday
|
7
7
|
zeitwerk
|
@@ -31,9 +31,10 @@ GEM
|
|
31
31
|
i18n (1.12.0)
|
32
32
|
concurrent-ruby (~> 1.0)
|
33
33
|
json (2.6.2)
|
34
|
+
language_server-protocol (3.17.0.1)
|
34
35
|
minitest (5.16.3)
|
35
36
|
parallel (1.22.1)
|
36
|
-
parser (3.1.
|
37
|
+
parser (3.1.3.0)
|
37
38
|
ast (~> 2.4.1)
|
38
39
|
public_suffix (5.0.0)
|
39
40
|
rainbow (3.1.1)
|
@@ -63,9 +64,9 @@ GEM
|
|
63
64
|
rubocop-ast (>= 1.23.0, < 2.0)
|
64
65
|
ruby-progressbar (~> 1.7)
|
65
66
|
unicode-display_width (>= 1.4.0, < 3.0)
|
66
|
-
rubocop-ast (1.
|
67
|
+
rubocop-ast (1.24.0)
|
67
68
|
parser (>= 3.1.1.0)
|
68
|
-
rubocop-performance (1.15.
|
69
|
+
rubocop-performance (1.15.1)
|
69
70
|
rubocop (>= 1.7.0, < 2.0)
|
70
71
|
rubocop-ast (>= 0.4.0)
|
71
72
|
rubocop-rspec (2.15.0)
|
@@ -78,9 +79,10 @@ GEM
|
|
78
79
|
simplecov_json_formatter (~> 0.1)
|
79
80
|
simplecov-html (0.12.3)
|
80
81
|
simplecov_json_formatter (0.1.4)
|
81
|
-
standard (1.
|
82
|
+
standard (1.19.0)
|
83
|
+
language_server-protocol (= 3.17.0.1)
|
82
84
|
rubocop (= 1.39.0)
|
83
|
-
rubocop-performance (= 1.15.
|
85
|
+
rubocop-performance (= 1.15.1)
|
84
86
|
tzinfo (2.0.5)
|
85
87
|
concurrent-ruby (~> 1.0)
|
86
88
|
unicode-display_width (2.3.0)
|
@@ -91,6 +93,7 @@ GEM
|
|
91
93
|
zeitwerk (2.6.6)
|
92
94
|
|
93
95
|
PLATFORMS
|
96
|
+
x86_64-darwin-19
|
94
97
|
x86_64-darwin-20
|
95
98
|
x86_64-darwin-21
|
96
99
|
x86_64-linux
|
@@ -106,4 +109,4 @@ DEPENDENCIES
|
|
106
109
|
webmock
|
107
110
|
|
108
111
|
BUNDLED WITH
|
109
|
-
2.3.
|
112
|
+
2.3.26
|
data/README.md
CHANGED
@@ -32,6 +32,8 @@ client = Globus::Client.configure(
|
|
32
32
|
transfer_endpoint_id: Settings.globus.transfer_endpoint_id
|
33
33
|
)
|
34
34
|
client.mkdir(user_id: 'mjgiarlo', work_id: 1234, work_version: 1)
|
35
|
+
|
36
|
+
result = client.user_exists?('mjgiarlo')
|
35
37
|
```
|
36
38
|
|
37
39
|
You can also invoke methods directly on the client class, which is useful in a
|
@@ -58,12 +60,31 @@ end
|
|
58
60
|
|
59
61
|
## Development
|
60
62
|
|
61
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
62
|
-
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
63
|
-
prompt that will allow you to experiment.
|
63
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
64
64
|
|
65
65
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
66
66
|
|
67
|
+
### Integration Testing
|
68
|
+
|
69
|
+
To test that the gem works against the Globus APIs, run `api_test.rb` via:
|
70
|
+
|
71
|
+
```shell
|
72
|
+
# NOTE: This is bash syntax, YMMV
|
73
|
+
$ export GLOBUS_CLIENT_ID=$(vault kv get -field=content puppet/application/sdr/globus/{prod|qa|stage}/client_id)
|
74
|
+
$ export GLOBUS_CLIENT_SECRET=$(vault kv get -field=content puppet/application/sdr/globus/{prod|qa|stage}/client_secret)
|
75
|
+
$ export GLOBUS_ENDPOINT=$(vault kv get -field=content puppet/application/sdr/globus/{prod|qa|stage}/endpoint_uuid)
|
76
|
+
$ export GLOBUS_UPLOADS_DIRECTORY=from_shared_configs
|
77
|
+
# NOTE: The three args below are a user ID, a work ID, and a work version
|
78
|
+
$ ./api_test.rb mjgiarlo 987 1
|
79
|
+
|
80
|
+
Initial directory permissions: rw
|
81
|
+
Number of files in directory: 2
|
82
|
+
Total size of files in directory: 66669
|
83
|
+
Final directory permissions: r
|
84
|
+
```
|
85
|
+
|
86
|
+
Inspect the output and compare it to what you see in Globus Personal Connect to determine if behavior is correct.
|
87
|
+
|
67
88
|
## Contributing
|
68
89
|
|
69
90
|
Bug reports and pull requests are welcome on GitHub at https://github.com/sul-dlss/globus_client.
|
data/api_test.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "globus/client"
|
6
|
+
|
7
|
+
Globus::Client.configure(
|
8
|
+
client_id: ENV["GLOBUS_CLIENT_ID"],
|
9
|
+
client_secret: ENV["GLOBUS_CLIENT_SECRET"],
|
10
|
+
uploads_directory: ENV["GLOBUS_UPLOADS_DIRECTORY"],
|
11
|
+
transfer_endpoint_id: ENV["GLOBUS_ENDPOINT"]
|
12
|
+
)
|
13
|
+
|
14
|
+
user_id, work_id, work_version = *ARGV
|
15
|
+
|
16
|
+
# Test public API methods here.
|
17
|
+
Globus::Client.mkdir(user_id:, work_id:, work_version:)
|
18
|
+
|
19
|
+
user_exists = Globus::Client.user_exists?(user_id)
|
20
|
+
|
21
|
+
# Not part of the public API but this allows us to test access changes
|
22
|
+
before_permissions = Globus::Client::Endpoint.new(Globus::Client.config, user_id: user_id, work_id: work_id, work_version: work_version).send(:access_rule)["permissions"]
|
23
|
+
|
24
|
+
files_count = Globus::Client.file_count(user_id:, work_id:, work_version:)
|
25
|
+
|
26
|
+
total_size = Globus::Client.total_size(user_id:, work_id:, work_version:)
|
27
|
+
|
28
|
+
Globus::Client.disallow_writes(user_id:, work_id:, work_version:)
|
29
|
+
|
30
|
+
# Not part of the public API but this allows us to test access changes
|
31
|
+
after_permissions = Globus::Client::Endpoint.new(Globus::Client.config, user_id: user_id, work_id: work_id, work_version: work_version).send(:access_rule)["permissions"]
|
32
|
+
|
33
|
+
puts "User #{user_id} exists: #{user_exists}"
|
34
|
+
puts "Initial directory permissions: #{before_permissions}"
|
35
|
+
puts "Number of files in directory: #{files_count}"
|
36
|
+
puts "Total size of files in directory: #{total_size}"
|
37
|
+
puts "Final directory permissions: #{after_permissions}"
|
@@ -15,22 +15,32 @@ module Globus
|
|
15
15
|
@work_version = work_version
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
def length
|
18
|
+
def file_count
|
20
19
|
objects["total"]
|
21
20
|
end
|
22
21
|
|
22
|
+
def total_size
|
23
|
+
files.sum { |file| file["size"] }
|
24
|
+
end
|
25
|
+
|
23
26
|
# Create a directory https://docs.globus.org/api/transfer/file_operations/#make_directory
|
24
27
|
def mkdir
|
25
28
|
# transfer API does not support recursive directory creation
|
26
29
|
paths.each do |path|
|
27
|
-
response =
|
30
|
+
response = connection.post("#{transfer_path}/mkdir") do |req|
|
31
|
+
req.headers["Content-Type"] = "application/json"
|
32
|
+
req.body = {
|
33
|
+
DATA_TYPE: "mkdir",
|
34
|
+
path:
|
35
|
+
}.to_json
|
36
|
+
end
|
37
|
+
|
28
38
|
next if response.success?
|
29
39
|
|
30
|
-
# if directory already exists
|
40
|
+
# Ignore error if directory already exists
|
31
41
|
if response.status == 502
|
32
42
|
error = JSON.parse(response.body)
|
33
|
-
next if error["code"] == "ExternalError.
|
43
|
+
next if error["code"] == "ExternalError.MkdirFailed.Exists"
|
34
44
|
end
|
35
45
|
|
36
46
|
UnexpectedResponse.call(response)
|
@@ -38,11 +48,13 @@ module Globus
|
|
38
48
|
end
|
39
49
|
|
40
50
|
# Assign a user read/write permissions for a directory https://docs.globus.org/api/transfer/acl/#rest_access_create
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
51
|
+
def allow_writes
|
52
|
+
access_request(permissions: "rw")
|
53
|
+
end
|
54
|
+
|
55
|
+
# Assign a user read-only permissions for a directory https://docs.globus.org/api/transfer/acl/#rest_access_create
|
56
|
+
def disallow_writes
|
57
|
+
access_request(permissions: "r")
|
46
58
|
end
|
47
59
|
|
48
60
|
private
|
@@ -57,6 +69,10 @@ module Globus
|
|
57
69
|
)
|
58
70
|
end
|
59
71
|
|
72
|
+
def user
|
73
|
+
Identity.new(config).get_identity_id(user_id)
|
74
|
+
end
|
75
|
+
|
60
76
|
# Builds up a path from a list of path elements. E.g., input would look like:
|
61
77
|
# ["mjgiarlo", "work123", "version1"]
|
62
78
|
# And this method returns:
|
@@ -67,52 +83,79 @@ module Globus
|
|
67
83
|
end
|
68
84
|
end
|
69
85
|
|
86
|
+
# @see #paths
|
87
|
+
def full_path
|
88
|
+
paths.last
|
89
|
+
end
|
90
|
+
|
70
91
|
def path_segments
|
71
92
|
[user_id, "work#{work_id}", "version#{work_version}"]
|
72
93
|
end
|
73
94
|
|
74
|
-
def
|
75
|
-
|
95
|
+
def objects
|
96
|
+
# List files at an endpoint https://docs.globus.org/api/transfer/file_operations/#list_directory_contents
|
97
|
+
response = connection.get("#{transfer_path}/ls?path=#{full_path}")
|
98
|
+
return JSON.parse(response.body) if response.success?
|
99
|
+
|
100
|
+
UnexpectedResponse.call(response)
|
76
101
|
end
|
77
102
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
103
|
+
def files
|
104
|
+
objects["DATA"].select { |object| object["DATA_TYPE"] == "file" }
|
105
|
+
end
|
106
|
+
|
107
|
+
def access_request(permissions:)
|
108
|
+
response = if access_rule_id
|
109
|
+
connection.put("#{access_path}/#{access_rule_id}") do |req|
|
110
|
+
req.body = {
|
111
|
+
DATA_TYPE: "access",
|
112
|
+
permissions:
|
113
|
+
}.to_json
|
114
|
+
req.headers["Content-Type"] = "application/json"
|
115
|
+
end
|
116
|
+
else
|
117
|
+
connection.post(access_path) do |req|
|
118
|
+
req.body = {
|
119
|
+
DATA_TYPE: "access",
|
120
|
+
principal_type: "identity",
|
121
|
+
principal: user,
|
122
|
+
path: full_path,
|
123
|
+
permissions:,
|
124
|
+
notify_email: "#{user_id}@stanford.edu"
|
125
|
+
}.to_json
|
126
|
+
req.headers["Content-Type"] = "application/json"
|
127
|
+
end
|
86
128
|
end
|
129
|
+
|
130
|
+
return response if response.success?
|
131
|
+
|
132
|
+
UnexpectedResponse.call(response)
|
87
133
|
end
|
88
134
|
|
89
|
-
|
90
|
-
|
91
|
-
# @param id [String] globus identifier associated with the user_id email
|
92
|
-
# @param user_id [String] user_id, not email address
|
93
|
-
# @return [Faraday::Response]
|
94
|
-
def call_access(path:, id:, user_id:)
|
95
|
-
response = connection.post("#{endpoint}/access") do |req|
|
96
|
-
req.body = {
|
97
|
-
DATA_TYPE: "access",
|
98
|
-
principal_type: "identity",
|
99
|
-
principal: id,
|
100
|
-
path:,
|
101
|
-
permissions: "rw",
|
102
|
-
notify_email: "#{user_id}@stanford.edu"
|
103
|
-
}.to_json
|
135
|
+
def access_rule
|
136
|
+
response = connection.get(access_list_path) do |req|
|
104
137
|
req.headers["Content-Type"] = "application/json"
|
105
138
|
end
|
106
|
-
UnexpectedResponse.call(response) unless response.success?
|
107
139
|
|
108
|
-
|
140
|
+
JSON
|
141
|
+
.parse(response.body)["DATA"]
|
142
|
+
.find { |acl| acl["path"] == full_path }
|
109
143
|
end
|
110
144
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
145
|
+
def access_rule_id
|
146
|
+
access_rule&.fetch("id")
|
147
|
+
end
|
148
|
+
|
149
|
+
def transfer_path
|
150
|
+
"/v0.10/operation/endpoint/#{config.transfer_endpoint_id}"
|
151
|
+
end
|
152
|
+
|
153
|
+
def access_path
|
154
|
+
"/v0.10/endpoint/#{config.transfer_endpoint_id}/access"
|
155
|
+
end
|
156
|
+
|
157
|
+
def access_list_path
|
158
|
+
"/v0.10/endpoint/#{config.transfer_endpoint_id}/access_list"
|
116
159
|
end
|
117
160
|
end
|
118
161
|
end
|
data/lib/globus/client.rb
CHANGED
@@ -36,7 +36,7 @@ module Globus
|
|
36
36
|
self
|
37
37
|
end
|
38
38
|
|
39
|
-
delegate :mkdir, :
|
39
|
+
delegate :config, :disallow_writes, :file_count, :mkdir, :total_size, :user_exists?, to: :instance
|
40
40
|
|
41
41
|
def default_transfer_url
|
42
42
|
"https://transfer.api.globusonline.org"
|
@@ -52,7 +52,27 @@ module Globus
|
|
52
52
|
def mkdir(...)
|
53
53
|
endpoint = Globus::Client::Endpoint.new(config, ...)
|
54
54
|
endpoint.mkdir
|
55
|
-
endpoint.
|
55
|
+
endpoint.allow_writes
|
56
|
+
end
|
57
|
+
|
58
|
+
def disallow_writes(...)
|
59
|
+
endpoint = Globus::Client::Endpoint.new(config, ...)
|
60
|
+
endpoint.disallow_writes
|
61
|
+
end
|
62
|
+
|
63
|
+
def file_count(...)
|
64
|
+
endpoint = Globus::Client::Endpoint.new(config, ...)
|
65
|
+
endpoint.file_count
|
66
|
+
end
|
67
|
+
|
68
|
+
def total_size(...)
|
69
|
+
endpoint = Globus::Client::Endpoint.new(config, ...)
|
70
|
+
endpoint.total_size
|
71
|
+
end
|
72
|
+
|
73
|
+
def user_exists?(...)
|
74
|
+
identity = Globus::Client::Identity.new(config)
|
75
|
+
identity.exists?(...)
|
56
76
|
end
|
57
77
|
end
|
58
78
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: globus_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Collier
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-12-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -164,6 +164,7 @@ files:
|
|
164
164
|
- LICENSE
|
165
165
|
- README.md
|
166
166
|
- Rakefile
|
167
|
+
- api_test.rb
|
167
168
|
- globus_client.gemspec
|
168
169
|
- lib/globus/client.rb
|
169
170
|
- lib/globus/client/authenticator.rb
|