google-cloud-storage 0.20.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.
@@ -0,0 +1,429 @@
1
+ # Copyright 2015 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ module Google
17
+ module Cloud
18
+ module Storage
19
+ class File
20
+ ##
21
+ # # File Access Control List
22
+ #
23
+ # Represents a File's Access Control List.
24
+ #
25
+ # @example
26
+ # require "google/cloud"
27
+ #
28
+ # gcloud = Google::Cloud.new
29
+ # storage = gcloud.storage
30
+ #
31
+ # bucket = storage.bucket "my-bucket"
32
+ #
33
+ # file = bucket.file "path/to/my-file.ext"
34
+ # file.acl.readers.each { |reader| puts reader }
35
+ #
36
+ class Acl
37
+ # @private
38
+ RULES = { "authenticatedRead" => "authenticatedRead",
39
+ "auth" => "authenticatedRead",
40
+ "auth_read" => "authenticatedRead",
41
+ "authenticated" => "authenticatedRead",
42
+ "authenticated_read" => "authenticatedRead",
43
+ "bucketOwnerFullControl" => "bucketOwnerFullControl",
44
+ "owner_full" => "bucketOwnerFullControl",
45
+ "bucketOwnerRead" => "bucketOwnerRead",
46
+ "owner_read" => "bucketOwnerRead",
47
+ "private" => "private",
48
+ "projectPrivate" => "projectPrivate",
49
+ "project_private" => "projectPrivate",
50
+ "publicRead" => "publicRead",
51
+ "public" => "publicRead",
52
+ "public_read" => "publicRead" }
53
+
54
+ ##
55
+ # @private Initialized a new Acl object.
56
+ # Must provide a valid Bucket object.
57
+ def initialize file
58
+ @bucket = file.bucket
59
+ @file = file.name
60
+ @service = file.service
61
+ @owners = nil
62
+ @readers = nil
63
+ end
64
+
65
+ ##
66
+ # Reloads all Access Control List data for the file.
67
+ #
68
+ # @example
69
+ # require "google/cloud"
70
+ #
71
+ # gcloud = Google::Cloud.new
72
+ # storage = gcloud.storage
73
+ #
74
+ # bucket = storage.bucket "my-bucket"
75
+ #
76
+ # file = bucket.file "path/to/my-file.ext"
77
+ # file.acl.reload!
78
+ #
79
+ def reload!
80
+ gapi = @service.list_file_acls @bucket, @file
81
+ acls = Array(gapi.items).map do |acl|
82
+ if acl.is_a? Google::Apis::StorageV1::ObjectAccessControl
83
+ return acl
84
+ end
85
+ fail "Unknown ACL format: #{acl.class}" unless acl.is_a? Hash
86
+ Google::Apis::StorageV1::ObjectAccessControl.from_json acl.to_json
87
+ end
88
+ @owners = entities_from_acls acls, "OWNER"
89
+ @readers = entities_from_acls acls, "READER"
90
+ end
91
+ alias_method :refresh!, :reload!
92
+
93
+ ##
94
+ # Lists the owners of the file.
95
+ #
96
+ # @return [Array<String>]
97
+ #
98
+ # @example
99
+ # require "google/cloud"
100
+ #
101
+ # gcloud = Google::Cloud.new
102
+ # storage = gcloud.storage
103
+ #
104
+ # bucket = storage.bucket "my-bucket"
105
+ #
106
+ # file = bucket.file "path/to/my-file.ext"
107
+ # file.acl.owners.each { |owner| puts owner }
108
+ #
109
+ def owners
110
+ reload! if @owners.nil?
111
+ @owners
112
+ end
113
+
114
+ ##
115
+ # Lists the readers of the file.
116
+ #
117
+ # @return [Array<String>]
118
+ #
119
+ # @example
120
+ # require "google/cloud"
121
+ #
122
+ # gcloud = Google::Cloud.new
123
+ # storage = gcloud.storage
124
+ #
125
+ # bucket = storage.bucket "my-bucket"
126
+ #
127
+ # file = bucket.file "path/to/my-file.ext"
128
+ # file.acl.readers.each { |reader| puts reader }
129
+ #
130
+ def readers
131
+ reload! if @readers.nil?
132
+ @readers
133
+ end
134
+
135
+ ##
136
+ # Grants owner permission to the file.
137
+ #
138
+ # @param [String] entity The entity holding the permission, in one of
139
+ # the following forms:
140
+ #
141
+ # * user-userId
142
+ # * user-email
143
+ # * group-groupId
144
+ # * group-email
145
+ # * domain-domain
146
+ # * project-team-projectId
147
+ # * allUsers
148
+ # * allAuthenticatedUsers
149
+ #
150
+ # @param [Integer] generation When present, selects a specific
151
+ # revision of this object. Default is the latest version.
152
+ #
153
+ # @example Grant access to a user by prepending `"user-"` to an email:
154
+ # require "google/cloud"
155
+ #
156
+ # gcloud = Google::Cloud.new
157
+ # storage = gcloud.storage
158
+ #
159
+ # bucket = storage.bucket "my-bucket"
160
+ #
161
+ # file = bucket.file "path/to/my-file.ext"
162
+ # email = "heidi@example.net"
163
+ # file.acl.add_owner "user-#{email}"
164
+ #
165
+ # @example Grant access to a group by prepending `"group-"` to email:
166
+ # require "google/cloud"
167
+ #
168
+ # gcloud = Google::Cloud.new
169
+ # storage = gcloud.storage
170
+ #
171
+ # bucket = storage.bucket "my-bucket"
172
+ #
173
+ # file = bucket.file "path/to/my-file.ext"
174
+ # email = "authors@example.net"
175
+ # file.acl.add_owner "group-#{email}"
176
+ #
177
+ def add_owner entity, generation: nil
178
+ options = { generation: generation }
179
+ gapi = @service.insert_file_acl @bucket, @file, entity, "OWNER",
180
+ options
181
+ entity = gapi.entity
182
+ @owners.push entity unless @owners.nil?
183
+ entity
184
+ end
185
+
186
+ ##
187
+ # Grants reader permission to the file.
188
+ #
189
+ # @param [String] entity The entity holding the permission, in one of
190
+ # the following forms:
191
+ #
192
+ # * user-userId
193
+ # * user-email
194
+ # * group-groupId
195
+ # * group-email
196
+ # * domain-domain
197
+ # * project-team-projectId
198
+ # * allUsers
199
+ # * allAuthenticatedUsers
200
+ #
201
+ # @param [Integer] generation When present, selects a specific
202
+ # revision of this object. Default is the latest version.
203
+ #
204
+ # @example Grant access to a user by prepending `"user-"` to an email:
205
+ # require "google/cloud"
206
+ #
207
+ # gcloud = Google::Cloud.new
208
+ # storage = gcloud.storage
209
+ #
210
+ # bucket = storage.bucket "my-bucket"
211
+ #
212
+ # file = bucket.file "path/to/my-file.ext"
213
+ # email = "heidi@example.net"
214
+ # file.acl.add_reader "user-#{email}"
215
+ #
216
+ # @example Grant access to a group by prepending `"group-"` to email:
217
+ # require "google/cloud"
218
+ #
219
+ # gcloud = Google::Cloud.new
220
+ # storage = gcloud.storage
221
+ #
222
+ # bucket = storage.bucket "my-bucket"
223
+ #
224
+ # file = bucket.file "path/to/my-file.ext"
225
+ # email = "authors@example.net"
226
+ # file.acl.add_reader "group-#{email}"
227
+ #
228
+ def add_reader entity, generation: nil
229
+ options = { generation: generation }
230
+ gapi = @service.insert_file_acl @bucket, @file, entity, "READER",
231
+ options
232
+ entity = gapi.entity
233
+ @readers.push entity unless @readers.nil?
234
+ entity
235
+ end
236
+
237
+ ##
238
+ # Permanently deletes the entity from the file's access control list.
239
+ #
240
+ # @param [String] entity The entity holding the permission, in one of
241
+ # the following forms:
242
+ #
243
+ # * user-userId
244
+ # * user-email
245
+ # * group-groupId
246
+ # * group-email
247
+ # * domain-domain
248
+ # * project-team-projectId
249
+ # * allUsers
250
+ # * allAuthenticatedUsers
251
+ #
252
+ # @param [Integer] generation When present, selects a specific
253
+ # revision of this object. Default is the latest version.
254
+ #
255
+ # @example
256
+ # require "google/cloud"
257
+ #
258
+ # gcloud = Google::Cloud.new
259
+ # storage = gcloud.storage
260
+ #
261
+ # bucket = storage.bucket "my-bucket"
262
+ #
263
+ # file = bucket.file "path/to/my-file.ext"
264
+ # email = "heidi@example.net"
265
+ # file.acl.delete "user-#{email}"
266
+ #
267
+ def delete entity, generation: nil
268
+ options = { generation: generation }
269
+ @service.delete_file_acl @bucket, @file, entity, options
270
+ @owners.delete entity unless @owners.nil?
271
+ @readers.delete entity unless @readers.nil?
272
+ true
273
+ end
274
+
275
+ # @private
276
+ def self.predefined_rule_for rule_name
277
+ RULES[rule_name.to_s]
278
+ end
279
+
280
+ # Predefined ACL helpers
281
+
282
+ ##
283
+ # Convenience method to apply the `authenticatedRead` predefined ACL
284
+ # rule to the file.
285
+ #
286
+ # @example
287
+ # require "google/cloud"
288
+ #
289
+ # gcloud = Google::Cloud.new
290
+ # storage = gcloud.storage
291
+ #
292
+ # bucket = storage.bucket "my-bucket"
293
+ #
294
+ # file = bucket.file "path/to/my-file.ext"
295
+ # file.acl.auth!
296
+ #
297
+ def auth!
298
+ update_predefined_acl! "authenticatedRead"
299
+ end
300
+ alias_method :authenticatedRead!, :auth!
301
+ alias_method :auth_read!, :auth!
302
+ alias_method :authenticated!, :auth!
303
+ alias_method :authenticated_read!, :auth!
304
+
305
+ ##
306
+ # Convenience method to apply the `bucketOwnerFullControl` predefined
307
+ # ACL rule to the file.
308
+ #
309
+ # @example
310
+ # require "google/cloud"
311
+ #
312
+ # gcloud = Google::Cloud.new
313
+ # storage = gcloud.storage
314
+ #
315
+ # bucket = storage.bucket "my-bucket"
316
+ #
317
+ # file = bucket.file "path/to/my-file.ext"
318
+ # file.acl.owner_full!
319
+ #
320
+ def owner_full!
321
+ update_predefined_acl! "bucketOwnerFullControl"
322
+ end
323
+ alias_method :bucketOwnerFullControl!, :owner_full!
324
+
325
+ ##
326
+ # Convenience method to apply the `bucketOwnerRead` predefined ACL
327
+ # rule to the file.
328
+ #
329
+ # @example
330
+ # require "google/cloud"
331
+ #
332
+ # gcloud = Google::Cloud.new
333
+ # storage = gcloud.storage
334
+ #
335
+ # bucket = storage.bucket "my-bucket"
336
+ #
337
+ # file = bucket.file "path/to/my-file.ext"
338
+ # file.acl.owner_read!
339
+ #
340
+ def owner_read!
341
+ update_predefined_acl! "bucketOwnerRead"
342
+ end
343
+ alias_method :bucketOwnerRead!, :owner_read!
344
+
345
+ ##
346
+ # Convenience method to apply the `private` predefined ACL
347
+ # rule to the file.
348
+ #
349
+ # @example
350
+ # require "google/cloud"
351
+ #
352
+ # gcloud = Google::Cloud.new
353
+ # storage = gcloud.storage
354
+ #
355
+ # bucket = storage.bucket "my-bucket"
356
+ #
357
+ # file = bucket.file "path/to/my-file.ext"
358
+ # file.acl.private!
359
+ #
360
+ def private!
361
+ update_predefined_acl! "private"
362
+ end
363
+
364
+ ##
365
+ # Convenience method to apply the `projectPrivate` predefined ACL
366
+ # rule to the file.
367
+ #
368
+ # @example
369
+ # require "google/cloud"
370
+ #
371
+ # gcloud = Google::Cloud.new
372
+ # storage = gcloud.storage
373
+ #
374
+ # bucket = storage.bucket "my-bucket"
375
+ #
376
+ # file = bucket.file "path/to/my-file.ext"
377
+ # file.acl.project_private!
378
+ #
379
+ def project_private!
380
+ update_predefined_acl! "projectPrivate"
381
+ end
382
+ alias_method :projectPrivate!, :project_private!
383
+
384
+ ##
385
+ # Convenience method to apply the `publicRead` predefined ACL
386
+ # rule to the file.
387
+ #
388
+ # @example
389
+ # require "google/cloud"
390
+ #
391
+ # gcloud = Google::Cloud.new
392
+ # storage = gcloud.storage
393
+ #
394
+ # bucket = storage.bucket "my-bucket"
395
+ #
396
+ # file = bucket.file "path/to/my-file.ext"
397
+ # file.acl.public!
398
+ #
399
+ def public!
400
+ update_predefined_acl! "publicRead"
401
+ end
402
+ alias_method :publicRead!, :public!
403
+ alias_method :public_read!, :public!
404
+
405
+ protected
406
+
407
+ def clear!
408
+ @owners = nil
409
+ @readers = nil
410
+ self
411
+ end
412
+
413
+ def update_predefined_acl! acl_role
414
+ patched_file = Google::Apis::StorageV1::Object.new acl: nil
415
+ @service.patch_file \
416
+ @bucket, @file, patched_file, predefined_acl: acl_role
417
+ clear!
418
+ end
419
+
420
+ def entities_from_acls acls, role
421
+ selected = acls.select { |acl| acl.role == role }
422
+ entities = selected.map(&:entity)
423
+ entities
424
+ end
425
+ end
426
+ end
427
+ end
428
+ end
429
+ end
@@ -0,0 +1,193 @@
1
+ # Copyright 2015 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "delegate"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Storage
21
+ class File
22
+ ##
23
+ # File::List is a special case Array with additional values.
24
+ class List < DelegateClass(::Array)
25
+ ##
26
+ # If not empty, indicates that there are more files that match the
27
+ # request and this value should be passed to the next
28
+ # {Google::Cloud::Storage::Bucket#files} to continue.
29
+ attr_accessor :token
30
+
31
+ # The list of prefixes of objects matching-but-not-listed up to and
32
+ # including the requested delimiter.
33
+ attr_accessor :prefixes
34
+
35
+ ##
36
+ # @private Create a new File::List with an array of values.
37
+ def initialize arr = []
38
+ super arr
39
+ end
40
+
41
+ ##
42
+ # Whether there is a next page of files.
43
+ #
44
+ # @return [Boolean]
45
+ #
46
+ # @example
47
+ # require "google/cloud"
48
+ #
49
+ # gcloud = Google::Cloud.new
50
+ # storage = gcloud.storage
51
+ #
52
+ # bucket = storage.bucket "my-bucket"
53
+ # files = bucket.files
54
+ # if files.next?
55
+ # next_files = files.next
56
+ # end
57
+ #
58
+ def next?
59
+ !token.nil?
60
+ end
61
+
62
+ ##
63
+ # Retrieve the next page of files.
64
+ #
65
+ # @return [File::List]
66
+ #
67
+ # @example
68
+ # require "google/cloud"
69
+ #
70
+ # gcloud = Google::Cloud.new
71
+ # storage = gcloud.storage
72
+ #
73
+ # bucket = storage.bucket "my-bucket"
74
+ # files = bucket.files
75
+ # if files.next?
76
+ # next_files = files.next
77
+ # end
78
+ #
79
+ def next
80
+ return nil unless next?
81
+ ensure_service!
82
+ options = {
83
+ prefix: @prefix, delimiter: @delimiter, token: @token, max: @max,
84
+ versions: @versions
85
+ }
86
+ gapi = @service.list_files @bucket, options
87
+ File::List.from_gapi gapi, @service, @bucket, @prefix,
88
+ @delimiter, @max, @versions
89
+ end
90
+
91
+ ##
92
+ # Retrieves all files by repeatedly loading {#next} until {#next?}
93
+ # returns `false`. Calls the given block once for each file, which is
94
+ # passed as the parameter.
95
+ #
96
+ # An Enumerator is returned if no block is given.
97
+ #
98
+ # This method may make several API calls until all files are
99
+ # retrieved. Be sure to use as narrow a search criteria as possible.
100
+ # Please use with caution.
101
+ #
102
+ # @param [Integer] request_limit The upper limit of API requests to
103
+ # make to load all files. Default is no limit.
104
+ # @yield [file] The block for accessing each file.
105
+ # @yieldparam [File] file The file object.
106
+ #
107
+ # @return [Enumerator]
108
+ #
109
+ # @example Iterating each file by passing a block:
110
+ # require "google/cloud"
111
+ #
112
+ # gcloud = Google::Cloud.new
113
+ # storage = gcloud.storage
114
+ #
115
+ # bucket = storage.bucket "my-bucket"
116
+ # files = bucket.files
117
+ # files.all do |file|
118
+ # puts file.name
119
+ # end
120
+ #
121
+ # @example Using the enumerator by not passing a block:
122
+ # require "google/cloud"
123
+ #
124
+ # gcloud = Google::Cloud.new
125
+ # storage = gcloud.storage
126
+ #
127
+ # bucket = storage.bucket "my-bucket"
128
+ # files = bucket.files
129
+ #
130
+ # all_names = files.all.map do |file|
131
+ # file.name
132
+ # end
133
+ #
134
+ # @example Limit the number of API calls made:
135
+ # require "google/cloud"
136
+ #
137
+ # gcloud = Google::Cloud.new
138
+ # storage = gcloud.storage
139
+ #
140
+ # bucket = storage.bucket "my-bucket"
141
+ # files = bucket.files
142
+ # files.all(request_limit: 10) do |file|
143
+ # puts file.name
144
+ # end
145
+ #
146
+ def all request_limit: nil
147
+ request_limit = request_limit.to_i if request_limit
148
+ unless block_given?
149
+ return enum_for(:all, request_limit: request_limit)
150
+ end
151
+ results = self
152
+ loop do
153
+ results.each { |r| yield r }
154
+ if request_limit
155
+ request_limit -= 1
156
+ break if request_limit < 0
157
+ end
158
+ break unless results.next?
159
+ results = results.next
160
+ end
161
+ end
162
+
163
+ ##
164
+ # @private New File::List from a Google API Client
165
+ # Google::Apis::StorageV1::Objects object.
166
+ def self.from_gapi gapi_list, service, bucket = nil, prefix = nil,
167
+ delimiter = nil, max = nil, versions = nil
168
+ files = new(Array(gapi_list.items).map do |gapi_object|
169
+ File.from_gapi gapi_object, service
170
+ end)
171
+ files.instance_variable_set :@token, gapi_list.next_page_token
172
+ files.instance_variable_set :@prefixes, Array(gapi_list.prefixes)
173
+ files.instance_variable_set :@service, service
174
+ files.instance_variable_set :@bucket, bucket
175
+ files.instance_variable_set :@prefix, prefix
176
+ files.instance_variable_set :@delimiter, delimiter
177
+ files.instance_variable_set :@max, max
178
+ files.instance_variable_set :@versions, versions
179
+ files
180
+ end
181
+
182
+ protected
183
+
184
+ ##
185
+ # Raise an error unless an active service is available.
186
+ def ensure_service!
187
+ fail "Must have active connection" unless @service
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end