google-cloud-storage 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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