google-cloud-storage 1.18.1 → 1.44.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +17 -30
- data/CHANGELOG.md +312 -0
- data/CONTRIBUTING.md +4 -5
- data/LOGGING.md +1 -1
- data/OVERVIEW.md +37 -5
- data/TROUBLESHOOTING.md +2 -8
- data/lib/google/cloud/storage/bucket/acl.rb +40 -40
- data/lib/google/cloud/storage/bucket/cors.rb +4 -1
- data/lib/google/cloud/storage/bucket/lifecycle.rb +259 -44
- data/lib/google/cloud/storage/bucket/list.rb +3 -3
- data/lib/google/cloud/storage/bucket.rb +1096 -172
- data/lib/google/cloud/storage/convert.rb +4 -3
- data/lib/google/cloud/storage/credentials.rb +16 -14
- data/lib/google/cloud/storage/errors.rb +7 -2
- data/lib/google/cloud/storage/file/acl.rb +181 -20
- data/lib/google/cloud/storage/file/list.rb +10 -8
- data/lib/google/cloud/storage/file/signer_v2.rb +36 -18
- data/lib/google/cloud/storage/file/signer_v4.rb +249 -61
- data/lib/google/cloud/storage/file/verifier.rb +2 -2
- data/lib/google/cloud/storage/file.rb +450 -84
- data/lib/google/cloud/storage/hmac_key/list.rb +182 -0
- data/lib/google/cloud/storage/hmac_key.rb +316 -0
- data/lib/google/cloud/storage/policy/binding.rb +246 -0
- data/lib/google/cloud/storage/policy/bindings.rb +196 -0
- data/lib/google/cloud/storage/policy/condition.rb +138 -0
- data/lib/google/cloud/storage/policy.rb +277 -24
- data/lib/google/cloud/storage/post_object.rb +20 -2
- data/lib/google/cloud/storage/project.rb +249 -50
- data/lib/google/cloud/storage/service.rb +479 -288
- data/lib/google/cloud/storage/version.rb +1 -1
- data/lib/google/cloud/storage.rb +86 -16
- data/lib/google-cloud-storage.rb +54 -7
- metadata +74 -27
@@ -25,12 +25,13 @@ module Google
|
|
25
25
|
def storage_class_for str
|
26
26
|
return nil if str.nil?
|
27
27
|
return str.map { |s| storage_class_for s } if str.is_a? Array
|
28
|
-
{ "
|
28
|
+
{ "archive" => "ARCHIVE",
|
29
|
+
"coldline" => "COLDLINE",
|
29
30
|
"dra" => "DURABLE_REDUCED_AVAILABILITY",
|
30
31
|
"durable" => "DURABLE_REDUCED_AVAILABILITY",
|
31
|
-
"
|
32
|
-
"coldline" => "COLDLINE",
|
32
|
+
"durable_reduced_availability" => "DURABLE_REDUCED_AVAILABILITY",
|
33
33
|
"multi_regional" => "MULTI_REGIONAL",
|
34
|
+
"nearline" => "NEARLINE",
|
34
35
|
"regional" => "REGIONAL",
|
35
36
|
"standard" => "STANDARD" }[str.to_s.downcase] || str.to_s
|
36
37
|
end
|
@@ -38,20 +38,22 @@ module Google
|
|
38
38
|
# storage.project_id #=> "my-project"
|
39
39
|
#
|
40
40
|
class Credentials < Google::Auth::Credentials
|
41
|
-
SCOPE =
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
41
|
+
SCOPE = ["https://www.googleapis.com/auth/devstorage.full_control"].freeze
|
42
|
+
PATH_ENV_VARS = [
|
43
|
+
"STORAGE_CREDENTIALS",
|
44
|
+
"STORAGE_KEYFILE",
|
45
|
+
"GOOGLE_CLOUD_CREDENTIALS",
|
46
|
+
"GOOGLE_CLOUD_KEYFILE",
|
47
|
+
"GCLOUD_KEYFILE"
|
48
|
+
].freeze
|
49
|
+
JSON_ENV_VARS = [
|
50
|
+
"STORAGE_CREDENTIALS_JSON",
|
51
|
+
"STORAGE_KEYFILE_JSON",
|
52
|
+
"GOOGLE_CLOUD_CREDENTIALS_JSON",
|
53
|
+
"GOOGLE_CLOUD_KEYFILE_JSON",
|
54
|
+
"GCLOUD_KEYFILE_JSON"
|
55
|
+
].freeze
|
56
|
+
DEFAULT_PATHS = ["~/.config/gcloud/application_default_credentials.json"].freeze
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -58,8 +58,13 @@ module Google
|
|
58
58
|
##
|
59
59
|
# # SignedUrlUnavailable Error
|
60
60
|
#
|
61
|
-
#
|
62
|
-
# missing credentials
|
61
|
+
# Raised by signed URL methods if the service account credentials
|
62
|
+
# are missing. Service account credentials are acquired by following the
|
63
|
+
# steps in [Service Account Authentication](
|
64
|
+
# https://cloud.google.com/iam/docs/service-accounts).
|
65
|
+
#
|
66
|
+
# @see https://cloud.google.com/storage/docs/access-control/signed-urls Signed URLs
|
67
|
+
#
|
63
68
|
class SignedUrlUnavailable < Google::Cloud::Error
|
64
69
|
end
|
65
70
|
end
|
@@ -190,7 +190,7 @@ module Google
|
|
190
190
|
generation: generation,
|
191
191
|
user_project: user_project
|
192
192
|
entity = gapi.entity
|
193
|
-
@owners
|
193
|
+
@owners&.push entity
|
194
194
|
entity
|
195
195
|
end
|
196
196
|
|
@@ -241,7 +241,7 @@ module Google
|
|
241
241
|
generation: generation,
|
242
242
|
user_project: user_project
|
243
243
|
entity = gapi.entity
|
244
|
-
@readers
|
244
|
+
@readers&.push entity
|
245
245
|
entity
|
246
246
|
end
|
247
247
|
|
@@ -281,8 +281,8 @@ module Google
|
|
281
281
|
@service.delete_file_acl \
|
282
282
|
@bucket, @file, entity,
|
283
283
|
generation: generation, user_project: user_project
|
284
|
-
@owners
|
285
|
-
@readers
|
284
|
+
@owners&.delete entity
|
285
|
+
@readers&.delete entity
|
286
286
|
true
|
287
287
|
end
|
288
288
|
|
@@ -297,6 +297,22 @@ module Google
|
|
297
297
|
# Convenience method to apply the `authenticatedRead` predefined ACL
|
298
298
|
# rule to the file.
|
299
299
|
#
|
300
|
+
# @param [Integer] generation Select a specific revision of the file to
|
301
|
+
# update. The default is the latest version.
|
302
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
303
|
+
# on whether the file's current generation matches the given value.
|
304
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
305
|
+
# versions of the file.
|
306
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
307
|
+
# on whether the file's current generation does not match the given
|
308
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
309
|
+
# makes the operation succeed only if there is a live version of the file.
|
310
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
311
|
+
# on whether the file's current metageneration matches the given value.
|
312
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
313
|
+
# conditional on whether the file's current metageneration does not
|
314
|
+
# match the given value.
|
315
|
+
#
|
300
316
|
# @example
|
301
317
|
# require "google/cloud/storage"
|
302
318
|
#
|
@@ -307,8 +323,17 @@ module Google
|
|
307
323
|
# file = bucket.file "path/to/my-file.ext"
|
308
324
|
# file.acl.auth!
|
309
325
|
#
|
310
|
-
def auth!
|
311
|
-
|
326
|
+
def auth! generation: nil,
|
327
|
+
if_generation_match: nil,
|
328
|
+
if_generation_not_match: nil,
|
329
|
+
if_metageneration_match: nil,
|
330
|
+
if_metageneration_not_match: nil
|
331
|
+
update_predefined_acl! "authenticatedRead",
|
332
|
+
generation: generation,
|
333
|
+
if_generation_match: if_generation_match,
|
334
|
+
if_generation_not_match: if_generation_not_match,
|
335
|
+
if_metageneration_match: if_metageneration_match,
|
336
|
+
if_metageneration_not_match: if_metageneration_not_match
|
312
337
|
end
|
313
338
|
alias authenticatedRead! auth!
|
314
339
|
alias auth_read! auth!
|
@@ -319,6 +344,22 @@ module Google
|
|
319
344
|
# Convenience method to apply the `bucketOwnerFullControl` predefined
|
320
345
|
# ACL rule to the file.
|
321
346
|
#
|
347
|
+
# @param [Integer] generation Select a specific revision of the file to
|
348
|
+
# update. The default is the latest version.
|
349
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
350
|
+
# on whether the file's current generation matches the given value.
|
351
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
352
|
+
# versions of the file.
|
353
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
354
|
+
# on whether the file's current generation does not match the given
|
355
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
356
|
+
# makes the operation succeed only if there is a live version of the file.
|
357
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
358
|
+
# on whether the file's current metageneration matches the given value.
|
359
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
360
|
+
# conditional on whether the file's current metageneration does not
|
361
|
+
# match the given value.
|
362
|
+
#
|
322
363
|
# @example
|
323
364
|
# require "google/cloud/storage"
|
324
365
|
#
|
@@ -329,8 +370,17 @@ module Google
|
|
329
370
|
# file = bucket.file "path/to/my-file.ext"
|
330
371
|
# file.acl.owner_full!
|
331
372
|
#
|
332
|
-
def owner_full!
|
333
|
-
|
373
|
+
def owner_full! generation: nil,
|
374
|
+
if_generation_match: nil,
|
375
|
+
if_generation_not_match: nil,
|
376
|
+
if_metageneration_match: nil,
|
377
|
+
if_metageneration_not_match: nil
|
378
|
+
update_predefined_acl! "bucketOwnerFullControl",
|
379
|
+
generation: generation,
|
380
|
+
if_generation_match: if_generation_match,
|
381
|
+
if_generation_not_match: if_generation_not_match,
|
382
|
+
if_metageneration_match: if_metageneration_match,
|
383
|
+
if_metageneration_not_match: if_metageneration_not_match
|
334
384
|
end
|
335
385
|
alias bucketOwnerFullControl! owner_full!
|
336
386
|
|
@@ -338,6 +388,22 @@ module Google
|
|
338
388
|
# Convenience method to apply the `bucketOwnerRead` predefined ACL
|
339
389
|
# rule to the file.
|
340
390
|
#
|
391
|
+
# @param [Integer] generation Select a specific revision of the file to
|
392
|
+
# update. The default is the latest version.
|
393
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
394
|
+
# on whether the file's current generation matches the given value.
|
395
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
396
|
+
# versions of the file.
|
397
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
398
|
+
# on whether the file's current generation does not match the given
|
399
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
400
|
+
# makes the operation succeed only if there is a live version of the file.
|
401
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
402
|
+
# on whether the file's current metageneration matches the given value.
|
403
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
404
|
+
# conditional on whether the file's current metageneration does not
|
405
|
+
# match the given value.
|
406
|
+
#
|
341
407
|
# @example
|
342
408
|
# require "google/cloud/storage"
|
343
409
|
#
|
@@ -348,8 +414,17 @@ module Google
|
|
348
414
|
# file = bucket.file "path/to/my-file.ext"
|
349
415
|
# file.acl.owner_read!
|
350
416
|
#
|
351
|
-
def owner_read!
|
352
|
-
|
417
|
+
def owner_read! generation: nil,
|
418
|
+
if_generation_match: nil,
|
419
|
+
if_generation_not_match: nil,
|
420
|
+
if_metageneration_match: nil,
|
421
|
+
if_metageneration_not_match: nil
|
422
|
+
update_predefined_acl! "bucketOwnerRead",
|
423
|
+
generation: generation,
|
424
|
+
if_generation_match: if_generation_match,
|
425
|
+
if_generation_not_match: if_generation_not_match,
|
426
|
+
if_metageneration_match: if_metageneration_match,
|
427
|
+
if_metageneration_not_match: if_metageneration_not_match
|
353
428
|
end
|
354
429
|
alias bucketOwnerRead! owner_read!
|
355
430
|
|
@@ -357,6 +432,22 @@ module Google
|
|
357
432
|
# Convenience method to apply the `private` predefined ACL
|
358
433
|
# rule to the file.
|
359
434
|
#
|
435
|
+
# @param [Integer] generation Select a specific revision of the file to
|
436
|
+
# update. The default is the latest version.
|
437
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
438
|
+
# on whether the file's current generation matches the given value.
|
439
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
440
|
+
# versions of the file.
|
441
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
442
|
+
# on whether the file's current generation does not match the given
|
443
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
444
|
+
# makes the operation succeed only if there is a live version of the file.
|
445
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
446
|
+
# on whether the file's current metageneration matches the given value.
|
447
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
448
|
+
# conditional on whether the file's current metageneration does not
|
449
|
+
# match the given value.
|
450
|
+
#
|
360
451
|
# @example
|
361
452
|
# require "google/cloud/storage"
|
362
453
|
#
|
@@ -367,14 +458,39 @@ module Google
|
|
367
458
|
# file = bucket.file "path/to/my-file.ext"
|
368
459
|
# file.acl.private!
|
369
460
|
#
|
370
|
-
def private!
|
371
|
-
|
461
|
+
def private! generation: nil,
|
462
|
+
if_generation_match: nil,
|
463
|
+
if_generation_not_match: nil,
|
464
|
+
if_metageneration_match: nil,
|
465
|
+
if_metageneration_not_match: nil
|
466
|
+
update_predefined_acl! "private",
|
467
|
+
generation: generation,
|
468
|
+
if_generation_match: if_generation_match,
|
469
|
+
if_generation_not_match: if_generation_not_match,
|
470
|
+
if_metageneration_match: if_metageneration_match,
|
471
|
+
if_metageneration_not_match: if_metageneration_not_match
|
372
472
|
end
|
373
473
|
|
374
474
|
##
|
375
475
|
# Convenience method to apply the `projectPrivate` predefined ACL
|
376
476
|
# rule to the file.
|
377
477
|
#
|
478
|
+
# @param [Integer] generation Select a specific revision of the file to
|
479
|
+
# update. The default is the latest version.
|
480
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
481
|
+
# on whether the file's current generation matches the given value.
|
482
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
483
|
+
# versions of the file.
|
484
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
485
|
+
# on whether the file's current generation does not match the given
|
486
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
487
|
+
# makes the operation succeed only if there is a live version of the file.
|
488
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
489
|
+
# on whether the file's current metageneration matches the given value.
|
490
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
491
|
+
# conditional on whether the file's current metageneration does not
|
492
|
+
# match the given value.
|
493
|
+
#
|
378
494
|
# @example
|
379
495
|
# require "google/cloud/storage"
|
380
496
|
#
|
@@ -385,8 +501,17 @@ module Google
|
|
385
501
|
# file = bucket.file "path/to/my-file.ext"
|
386
502
|
# file.acl.project_private!
|
387
503
|
#
|
388
|
-
def project_private!
|
389
|
-
|
504
|
+
def project_private! generation: nil,
|
505
|
+
if_generation_match: nil,
|
506
|
+
if_generation_not_match: nil,
|
507
|
+
if_metageneration_match: nil,
|
508
|
+
if_metageneration_not_match: nil
|
509
|
+
update_predefined_acl! "projectPrivate",
|
510
|
+
generation: generation,
|
511
|
+
if_generation_match: if_generation_match,
|
512
|
+
if_generation_not_match: if_generation_not_match,
|
513
|
+
if_metageneration_match: if_metageneration_match,
|
514
|
+
if_metageneration_not_match: if_metageneration_not_match
|
390
515
|
end
|
391
516
|
alias projectPrivate! project_private!
|
392
517
|
|
@@ -394,6 +519,22 @@ module Google
|
|
394
519
|
# Convenience method to apply the `publicRead` predefined ACL
|
395
520
|
# rule to the file.
|
396
521
|
#
|
522
|
+
# @param [Integer] generation Select a specific revision of the file to
|
523
|
+
# update. The default is the latest version.
|
524
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
525
|
+
# on whether the file's current generation matches the given value.
|
526
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
527
|
+
# versions of the file.
|
528
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
529
|
+
# on whether the file's current generation does not match the given
|
530
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
531
|
+
# makes the operation succeed only if there is a live version of the file.
|
532
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
533
|
+
# on whether the file's current metageneration matches the given value.
|
534
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
535
|
+
# conditional on whether the file's current metageneration does not
|
536
|
+
# match the given value.
|
537
|
+
#
|
397
538
|
# @example
|
398
539
|
# require "google/cloud/storage"
|
399
540
|
#
|
@@ -404,8 +545,17 @@ module Google
|
|
404
545
|
# file = bucket.file "path/to/my-file.ext"
|
405
546
|
# file.acl.public!
|
406
547
|
#
|
407
|
-
def public!
|
408
|
-
|
548
|
+
def public! generation: nil,
|
549
|
+
if_generation_match: nil,
|
550
|
+
if_generation_not_match: nil,
|
551
|
+
if_metageneration_match: nil,
|
552
|
+
if_metageneration_not_match: nil
|
553
|
+
update_predefined_acl! "publicRead",
|
554
|
+
generation: generation,
|
555
|
+
if_generation_match: if_generation_match,
|
556
|
+
if_generation_not_match: if_generation_not_match,
|
557
|
+
if_metageneration_match: if_metageneration_match,
|
558
|
+
if_metageneration_not_match: if_metageneration_not_match
|
409
559
|
end
|
410
560
|
alias publicRead! public!
|
411
561
|
alias public_read! public!
|
@@ -418,9 +568,21 @@ module Google
|
|
418
568
|
self
|
419
569
|
end
|
420
570
|
|
421
|
-
def update_predefined_acl! acl_role
|
571
|
+
def update_predefined_acl! acl_role,
|
572
|
+
generation: nil,
|
573
|
+
if_generation_match: nil,
|
574
|
+
if_generation_not_match: nil,
|
575
|
+
if_metageneration_match: nil,
|
576
|
+
if_metageneration_not_match: nil
|
422
577
|
patched_file = Google::Apis::StorageV1::Object.new acl: []
|
423
|
-
@service.patch_file @bucket,
|
578
|
+
@service.patch_file @bucket,
|
579
|
+
@file,
|
580
|
+
patched_file,
|
581
|
+
generation: generation,
|
582
|
+
if_generation_match: if_generation_match,
|
583
|
+
if_generation_not_match: if_generation_not_match,
|
584
|
+
if_metageneration_match: if_metageneration_match,
|
585
|
+
if_metageneration_not_match: if_metageneration_not_match,
|
424
586
|
predefined_acl: acl_role,
|
425
587
|
user_project: user_project
|
426
588
|
clear!
|
@@ -428,8 +590,7 @@ module Google
|
|
428
590
|
|
429
591
|
def entities_from_acls acls, role
|
430
592
|
selected = acls.select { |acl| acl.role == role }
|
431
|
-
|
432
|
-
entities
|
593
|
+
selected.map(&:entity)
|
433
594
|
end
|
434
595
|
end
|
435
596
|
end
|
@@ -77,11 +77,13 @@ module Google
|
|
77
77
|
def next
|
78
78
|
return nil unless next?
|
79
79
|
ensure_service!
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
80
|
+
|
81
|
+
gapi = @service.list_files @bucket, prefix: @prefix,
|
82
|
+
delimiter: @delimiter,
|
83
|
+
token: @token,
|
84
|
+
max: @max,
|
85
|
+
versions: @versions,
|
86
|
+
user_project: @user_project
|
85
87
|
File::List.from_gapi gapi, @service, @bucket, @prefix,
|
86
88
|
@delimiter, @max, @versions,
|
87
89
|
user_project: @user_project
|
@@ -139,17 +141,17 @@ module Google
|
|
139
141
|
# puts file.name
|
140
142
|
# end
|
141
143
|
#
|
142
|
-
def all request_limit: nil
|
144
|
+
def all request_limit: nil, &block
|
143
145
|
request_limit = request_limit.to_i if request_limit
|
144
146
|
unless block_given?
|
145
147
|
return enum_for :all, request_limit: request_limit
|
146
148
|
end
|
147
149
|
results = self
|
148
150
|
loop do
|
149
|
-
results.each
|
151
|
+
results.each(&block)
|
150
152
|
if request_limit
|
151
153
|
request_limit -= 1
|
152
|
-
break if request_limit
|
154
|
+
break if request_limit.negative?
|
153
155
|
end
|
154
156
|
break unless results.next?
|
155
157
|
results = results.next
|
@@ -41,9 +41,20 @@ module Google
|
|
41
41
|
end
|
42
42
|
|
43
43
|
##
|
44
|
-
# The external path to the file.
|
44
|
+
# The external path to the file, URI-encoded.
|
45
|
+
# Will not URI encode the special `${filename}` variable.
|
46
|
+
# "You can also use the ${filename} variable..."
|
47
|
+
# https://cloud.google.com/storage/docs/xml-api/post-object
|
48
|
+
#
|
45
49
|
def ext_path
|
46
|
-
|
50
|
+
path = "/#{@bucket}/#{@path}"
|
51
|
+
escaped = Addressable::URI.encode_component path, Addressable::URI::CharacterClasses::PATH
|
52
|
+
special_var = "${filename}"
|
53
|
+
# Restore the unencoded `${filename}` variable, if present.
|
54
|
+
if path.include? special_var
|
55
|
+
return escaped.gsub "$%7Bfilename%7D", special_var
|
56
|
+
end
|
57
|
+
escaped
|
47
58
|
end
|
48
59
|
|
49
60
|
##
|
@@ -66,13 +77,21 @@ module Google
|
|
66
77
|
end
|
67
78
|
|
68
79
|
def determine_signing_key options = {}
|
69
|
-
options[:signing_key] || options[:private_key] ||
|
70
|
-
|
80
|
+
signing_key = options[:signing_key] || options[:private_key] ||
|
81
|
+
options[:signer] || @service.credentials.signing_key
|
82
|
+
raise SignedUrlUnavailable, error_msg("signing_key (private_key, signer)") unless signing_key
|
83
|
+
signing_key
|
71
84
|
end
|
72
85
|
|
73
86
|
def determine_issuer options = {}
|
74
|
-
options[:issuer] || options[:client_email] ||
|
75
|
-
|
87
|
+
issuer = options[:issuer] || options[:client_email] || @service.credentials.issuer
|
88
|
+
raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer
|
89
|
+
issuer
|
90
|
+
end
|
91
|
+
|
92
|
+
def error_msg attr_name
|
93
|
+
"Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
|
94
|
+
"see https://cloud.google.com/iam/docs/service-accounts"
|
76
95
|
end
|
77
96
|
|
78
97
|
def post_object options
|
@@ -88,8 +107,6 @@ module Google
|
|
88
107
|
i = determine_issuer options
|
89
108
|
s = determine_signing_key options
|
90
109
|
|
91
|
-
raise SignedUrlUnavailable unless i && s
|
92
|
-
|
93
110
|
policy_str = p.to_json
|
94
111
|
policy = Base64.strict_encode64(policy_str).delete "\n"
|
95
112
|
|
@@ -108,18 +125,21 @@ module Google
|
|
108
125
|
i = determine_issuer options
|
109
126
|
s = determine_signing_key options
|
110
127
|
|
111
|
-
raise SignedUrlUnavailable unless i && s
|
112
|
-
|
113
128
|
sig = generate_signature s, signature_str(options)
|
114
129
|
generate_signed_url i, sig, options[:expires], options[:query]
|
115
130
|
end
|
116
131
|
|
117
132
|
def generate_signature signing_key, secret
|
118
|
-
|
119
|
-
|
133
|
+
unencoded_signature = ""
|
134
|
+
if signing_key.is_a? Proc
|
135
|
+
unencoded_signature = signing_key.call secret
|
136
|
+
else
|
137
|
+
unless signing_key.respond_to? :sign
|
138
|
+
signing_key = OpenSSL::PKey::RSA.new signing_key
|
139
|
+
end
|
140
|
+
unencoded_signature = signing_key.sign OpenSSL::Digest::SHA256.new, secret
|
120
141
|
end
|
121
|
-
|
122
|
-
Base64.strict_encode64(signature).delete "\n"
|
142
|
+
Base64.strict_encode64(unencoded_signature).delete "\n"
|
123
143
|
end
|
124
144
|
|
125
145
|
def generate_signed_url issuer, signed_string, expires, query
|
@@ -127,10 +147,8 @@ module Google
|
|
127
147
|
"&Expires=#{expires}" \
|
128
148
|
"&Signature=#{url_escape signed_string}"
|
129
149
|
|
130
|
-
|
131
|
-
|
132
|
-
url << "&#{url_escape name}=#{url_escape value}"
|
133
|
-
end
|
150
|
+
query&.each do |name, value|
|
151
|
+
url << "&#{url_escape name}=#{url_escape value}"
|
134
152
|
end
|
135
153
|
|
136
154
|
url
|