google-cloud-storage 1.18.1 → 1.44.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/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
|