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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77e44f70f4c6ee02299ac4718e8ed5d1c2c88d58c71a4ba2c3bfbe970e2bb5df
4
- data.tar.gz: b74fbc9c11f7b9c9fdadac074fe8709711f0065d03ab01fcecb159374446bb9b
3
+ metadata.gz: 7a4c2d5c57d5c7439a64bf4a0c9da297422987a026ff9eafdb38722df11de72c
4
+ data.tar.gz: 48b723cfdcad41ccd033dcb57ea2e09ad1da8ec139f7a98cf36a6c264565898c
5
5
  SHA512:
6
- metadata.gz: 26d0923724fc1301b344b190d347abd25a1c6e17c57214f424df46d3739fc64ead270e9ae8eb3eddecdfc6700d6c52bc935cda654aef8109a01b45a5d187ca39
7
- data.tar.gz: a5c9e21ec3917f8c560ed34eaefb38af1253cddd582223e1986a78d165301443b689875a20a96f24ef1eb514aca19fbc7994af52c1f441b5db60d9428592cd0b
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.0)
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.2.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.23.0)
67
+ rubocop-ast (1.24.0)
67
68
  parser (>= 3.1.1.0)
68
- rubocop-performance (1.15.0)
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.18.0)
82
+ standard (1.19.0)
83
+ language_server-protocol (= 3.17.0.1)
82
84
  rubocop (= 1.39.0)
83
- rubocop-performance (= 1.15.0)
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.19
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
- # This is a temporary method to show parsing of data returned.
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 = call_mkdir(path)
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.MkdirFailedExists"
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 set_permissions
42
- path = "#{config.uploads_directory}/#{user_id}/work#{work_id}/version#{work_version}/"
43
- identity = Globus::Client::Identity.new(config)
44
- id = identity.get_identity_id(user_id)
45
- call_access(path:, id:, user_id:)
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 endpoint
75
- "/v0.10/operation/endpoint/#{config.transfer_endpoint_id}"
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
- # @return [Faraday::Response]
79
- def call_mkdir(path)
80
- connection.post("#{endpoint}/mkdir") do |req|
81
- req.headers["Content-Type"] = "application/json"
82
- req.body = {
83
- DATA_TYPE: "mkdir",
84
- path:
85
- }.to_json
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
- # Makes the API call to Globus to set permissions
90
- # @param path [String] the directory on the globus endpoint
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
- response
140
+ JSON
141
+ .parse(response.body)["DATA"]
142
+ .find { |acl| acl["path"] == full_path }
109
143
  end
110
144
 
111
- def objects
112
- # List files at an endpoint https://docs.globus.org/api/transfer/file_operations/#list_directory_contents
113
- response = connection.get("#{endpoint}/ls")
114
- UnexpectedResponse.call(response) unless response.success?
115
- JSON.parse(response.body)
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
@@ -18,6 +18,13 @@ module Globus
18
18
  extract_id(data)
19
19
  end
20
20
 
21
+ def exists?(sunetid)
22
+ get_identity_id(sunetid)
23
+ true
24
+ rescue
25
+ false
26
+ end
27
+
21
28
  private
22
29
 
23
30
  attr_reader :config
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Globus
4
4
  class Client
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
data/lib/globus/client.rb CHANGED
@@ -36,7 +36,7 @@ module Globus
36
36
  self
37
37
  end
38
38
 
39
- delegate :mkdir, :config, to: :instance
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.set_permissions
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.2.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-11-21 00:00:00.000000000 Z
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