mss-sdk 1.0.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 +7 -0
- data/.yardopts +9 -0
- data/LICENSE.txt +0 -0
- data/README.md +192 -0
- data/bin/mss-rb +178 -0
- data/ca-bundle.crt +3554 -0
- data/lib/mss/core/async_handle.rb +89 -0
- data/lib/mss/core/cacheable.rb +76 -0
- data/lib/mss/core/client.rb +786 -0
- data/lib/mss/core/collection/simple.rb +81 -0
- data/lib/mss/core/collection/with_limit_and_next_token.rb +70 -0
- data/lib/mss/core/collection/with_next_token.rb +96 -0
- data/lib/mss/core/collection.rb +262 -0
- data/lib/mss/core/configuration.rb +527 -0
- data/lib/mss/core/credential_providers.rb +653 -0
- data/lib/mss/core/data.rb +251 -0
- data/lib/mss/core/deprecations.rb +83 -0
- data/lib/mss/core/endpoints.rb +36 -0
- data/lib/mss/core/http/connection_pool.rb +374 -0
- data/lib/mss/core/http/curb_handler.rb +150 -0
- data/lib/mss/core/http/handler.rb +88 -0
- data/lib/mss/core/http/net_http_handler.rb +144 -0
- data/lib/mss/core/http/patch.rb +98 -0
- data/lib/mss/core/http/request.rb +258 -0
- data/lib/mss/core/http/response.rb +80 -0
- data/lib/mss/core/indifferent_hash.rb +87 -0
- data/lib/mss/core/inflection.rb +55 -0
- data/lib/mss/core/ini_parser.rb +41 -0
- data/lib/mss/core/json_client.rb +46 -0
- data/lib/mss/core/json_parser.rb +75 -0
- data/lib/mss/core/json_request_builder.rb +34 -0
- data/lib/mss/core/json_response_parser.rb +78 -0
- data/lib/mss/core/lazy_error_classes.rb +107 -0
- data/lib/mss/core/log_formatter.rb +426 -0
- data/lib/mss/core/managed_file.rb +31 -0
- data/lib/mss/core/meta_utils.rb +44 -0
- data/lib/mss/core/model.rb +61 -0
- data/lib/mss/core/naming.rb +29 -0
- data/lib/mss/core/option_grammar.rb +737 -0
- data/lib/mss/core/options/json_serializer.rb +81 -0
- data/lib/mss/core/options/validator.rb +154 -0
- data/lib/mss/core/options/xml_serializer.rb +117 -0
- data/lib/mss/core/page_result.rb +74 -0
- data/lib/mss/core/policy.rb +938 -0
- data/lib/mss/core/query_client.rb +40 -0
- data/lib/mss/core/query_error_parser.rb +23 -0
- data/lib/mss/core/query_request_builder.rb +46 -0
- data/lib/mss/core/query_response_parser.rb +34 -0
- data/lib/mss/core/region.rb +84 -0
- data/lib/mss/core/region_collection.rb +79 -0
- data/lib/mss/core/resource.rb +412 -0
- data/lib/mss/core/resource_cache.rb +39 -0
- data/lib/mss/core/response.rb +214 -0
- data/lib/mss/core/response_cache.rb +49 -0
- data/lib/mss/core/rest_error_parser.rb +23 -0
- data/lib/mss/core/rest_json_client.rb +39 -0
- data/lib/mss/core/rest_request_builder.rb +153 -0
- data/lib/mss/core/rest_response_parser.rb +65 -0
- data/lib/mss/core/rest_xml_client.rb +46 -0
- data/lib/mss/core/service_interface.rb +82 -0
- data/lib/mss/core/signers/base.rb +45 -0
- data/lib/mss/core/signers/cloud_front.rb +55 -0
- data/lib/mss/core/signers/s3.rb +158 -0
- data/lib/mss/core/signers/version_2.rb +71 -0
- data/lib/mss/core/signers/version_3.rb +85 -0
- data/lib/mss/core/signers/version_3_https.rb +60 -0
- data/lib/mss/core/signers/version_4/chunk_signed_stream.rb +190 -0
- data/lib/mss/core/signers/version_4.rb +227 -0
- data/lib/mss/core/uri_escape.rb +43 -0
- data/lib/mss/core/xml/frame.rb +245 -0
- data/lib/mss/core/xml/frame_stack.rb +84 -0
- data/lib/mss/core/xml/grammar.rb +306 -0
- data/lib/mss/core/xml/parser.rb +69 -0
- data/lib/mss/core/xml/root_frame.rb +64 -0
- data/lib/mss/core/xml/sax_handlers/libxml.rb +46 -0
- data/lib/mss/core/xml/sax_handlers/nokogiri.rb +55 -0
- data/lib/mss/core/xml/sax_handlers/ox.rb +40 -0
- data/lib/mss/core/xml/sax_handlers/rexml.rb +46 -0
- data/lib/mss/core/xml/stub.rb +122 -0
- data/lib/mss/core.rb +602 -0
- data/lib/mss/errors.rb +161 -0
- data/lib/mss/rails.rb +194 -0
- data/lib/mss/s3/access_control_list.rb +262 -0
- data/lib/mss/s3/acl_object.rb +263 -0
- data/lib/mss/s3/acl_options.rb +200 -0
- data/lib/mss/s3/bucket.rb +757 -0
- data/lib/mss/s3/bucket_collection.rb +161 -0
- data/lib/mss/s3/bucket_lifecycle_configuration.rb +472 -0
- data/lib/mss/s3/bucket_region_cache.rb +51 -0
- data/lib/mss/s3/bucket_tag_collection.rb +110 -0
- data/lib/mss/s3/bucket_version_collection.rb +78 -0
- data/lib/mss/s3/cipher_io.rb +119 -0
- data/lib/mss/s3/client/xml.rb +265 -0
- data/lib/mss/s3/client.rb +2076 -0
- data/lib/mss/s3/config.rb +60 -0
- data/lib/mss/s3/cors_rule.rb +107 -0
- data/lib/mss/s3/cors_rule_collection.rb +193 -0
- data/lib/mss/s3/data_options.rb +190 -0
- data/lib/mss/s3/encryption_utils.rb +145 -0
- data/lib/mss/s3/errors.rb +93 -0
- data/lib/mss/s3/multipart_upload.rb +353 -0
- data/lib/mss/s3/multipart_upload_collection.rb +75 -0
- data/lib/mss/s3/object_collection.rb +355 -0
- data/lib/mss/s3/object_metadata.rb +102 -0
- data/lib/mss/s3/object_upload_collection.rb +76 -0
- data/lib/mss/s3/object_version.rb +153 -0
- data/lib/mss/s3/object_version_collection.rb +88 -0
- data/lib/mss/s3/paginated_collection.rb +74 -0
- data/lib/mss/s3/policy.rb +73 -0
- data/lib/mss/s3/prefix_and_delimiter_collection.rb +46 -0
- data/lib/mss/s3/prefixed_collection.rb +84 -0
- data/lib/mss/s3/presign_v4.rb +135 -0
- data/lib/mss/s3/presigned_post.rb +574 -0
- data/lib/mss/s3/region_detection.rb +75 -0
- data/lib/mss/s3/request.rb +61 -0
- data/lib/mss/s3/s3_object.rb +1795 -0
- data/lib/mss/s3/tree/branch_node.rb +67 -0
- data/lib/mss/s3/tree/child_collection.rb +103 -0
- data/lib/mss/s3/tree/leaf_node.rb +93 -0
- data/lib/mss/s3/tree/node.rb +21 -0
- data/lib/mss/s3/tree/parent.rb +86 -0
- data/lib/mss/s3/tree.rb +115 -0
- data/lib/mss/s3/uploaded_part.rb +81 -0
- data/lib/mss/s3/uploaded_part_collection.rb +83 -0
- data/lib/mss/s3/website_configuration.rb +101 -0
- data/lib/mss/s3.rb +161 -0
- data/lib/mss/version.rb +16 -0
- data/lib/mss-sdk.rb +2 -0
- data/lib/mss.rb +14 -0
- data/rails/init.rb +14 -0
- metadata +201 -0
@@ -0,0 +1,263 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
require 'rexml/text'
|
14
|
+
|
15
|
+
module MSS
|
16
|
+
class S3
|
17
|
+
|
18
|
+
# Common methods for AccessControlList and related objects.
|
19
|
+
module ACLObject
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
def initialize(opts = {}); end
|
23
|
+
|
24
|
+
# @api private
|
25
|
+
def body_xml; ""; end
|
26
|
+
|
27
|
+
# @api private
|
28
|
+
def stag
|
29
|
+
element_name
|
30
|
+
end
|
31
|
+
|
32
|
+
# @api private
|
33
|
+
def element_name
|
34
|
+
self.class.name[/::([^:]*)$/, 1]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the XML representation of the object. Generally
|
38
|
+
# you'll want to call this on an AccessControlList object,
|
39
|
+
# which will yield an XML representation of the ACL that you
|
40
|
+
# can send to S3.
|
41
|
+
def to_s
|
42
|
+
if body_xml.empty?
|
43
|
+
"<#{stag}/>"
|
44
|
+
else
|
45
|
+
"<#{stag}>#{body_xml}</#{element_name}>"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# (see #to_s)
|
50
|
+
def to_xml
|
51
|
+
to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns true if and only if this object is valid according
|
55
|
+
# to S3's published ACL schema. In particular, this will
|
56
|
+
# check that all required attributes are provided and that
|
57
|
+
# they are of the correct type.
|
58
|
+
def valid?
|
59
|
+
validate!
|
60
|
+
rescue => e
|
61
|
+
false
|
62
|
+
else
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
# Raises an exception unless this object is valid according to
|
67
|
+
# S3's published ACL schema.
|
68
|
+
# @see #valid?
|
69
|
+
def validate!; end
|
70
|
+
|
71
|
+
# @api private
|
72
|
+
def validate_input(name, value, context = nil)
|
73
|
+
send("validate_#{name}_input!", value, context)
|
74
|
+
end
|
75
|
+
|
76
|
+
# @api private
|
77
|
+
module ClassMethods
|
78
|
+
|
79
|
+
def string_attr(element_name, options = {})
|
80
|
+
method_name = options[:method_name] ||
|
81
|
+
Core::Inflection.ruby_name(element_name)
|
82
|
+
|
83
|
+
attr_accessor(method_name)
|
84
|
+
setter_option(method_name)
|
85
|
+
string_input_validator(method_name)
|
86
|
+
validate_string(method_name) if options[:required]
|
87
|
+
body_xml_string_content(element_name, method_name)
|
88
|
+
end
|
89
|
+
|
90
|
+
def object_attr(klass, options = {})
|
91
|
+
base_name = klass.name[/::([^:]*)$/, 1]
|
92
|
+
method_name = Core::Inflection.ruby_name(base_name)
|
93
|
+
cast = options[:cast] || Hash
|
94
|
+
|
95
|
+
attr_reader(method_name)
|
96
|
+
setter_option(method_name)
|
97
|
+
object_setter(klass, method_name, cast)
|
98
|
+
object_input_validator(klass, base_name, method_name, cast)
|
99
|
+
validate_object(method_name) if options[:required]
|
100
|
+
body_xml_content(method_name)
|
101
|
+
end
|
102
|
+
|
103
|
+
def object_list_attr(list_element, klass, options = {})
|
104
|
+
base_name = klass.name[/::([^:]*)$/, 1]
|
105
|
+
method_name = Core::Inflection.ruby_name(options[:method_name].to_s || list_element)
|
106
|
+
default_value = nil
|
107
|
+
default_value = [] if options[:required]
|
108
|
+
|
109
|
+
attr_reader(method_name)
|
110
|
+
setter_option(method_name) { [] if options[:required] }
|
111
|
+
object_list_setter(klass, method_name)
|
112
|
+
object_list_input_validator(klass, base_name, method_name)
|
113
|
+
validate_list(method_name)
|
114
|
+
body_xml_list_content(list_element, method_name)
|
115
|
+
end
|
116
|
+
|
117
|
+
def setter_option(method_name)
|
118
|
+
Core::MetaUtils.class_extend_method(self, :initialize) do |*args|
|
119
|
+
opts = args.last || {}
|
120
|
+
instance_variable_set("@#{method_name}", yield) if block_given?
|
121
|
+
key = method_name.to_sym
|
122
|
+
|
123
|
+
if opts.has_key?(key)
|
124
|
+
value = opts[key]
|
125
|
+
validate_input(method_name, value, "for #{method_name} option")
|
126
|
+
self.send("#{method_name}=", value)
|
127
|
+
end
|
128
|
+
super(opts)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def string_input_validator(method_name)
|
133
|
+
input_validator(method_name) do |value, context|
|
134
|
+
raise ArgumentError.new("expected string"+context) unless
|
135
|
+
value.respond_to?(:to_str)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def object_input_validator(klass, base_name, method_name, cast)
|
140
|
+
input_validator(method_name) do |value, context|
|
141
|
+
if value.kind_of?(cast)
|
142
|
+
klass.new(value).validate!
|
143
|
+
else
|
144
|
+
raise ArgumentError.new("expected #{base_name} object or hash"+context) unless
|
145
|
+
value.nil? or value.kind_of? klass
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def object_list_input_validator(klass, base_name, method_name)
|
151
|
+
input_validator(method_name) do |value, context|
|
152
|
+
raise ArgumentError.new("expected array"+context) unless value.kind_of?(Array)
|
153
|
+
value.each do |member|
|
154
|
+
if member.kind_of?(Hash)
|
155
|
+
klass.new(member).validate!
|
156
|
+
else
|
157
|
+
raise ArgumentError.new("expected array#{context} "+
|
158
|
+
"to contain #{base_name} objects "+
|
159
|
+
"or hashes") unless
|
160
|
+
member.kind_of? klass
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def input_validator(method_name, &blk)
|
167
|
+
validator = "__validator__#{blk.object_id}"
|
168
|
+
Core::MetaUtils.class_extend_method(self, validator, &blk)
|
169
|
+
Core::MetaUtils.class_extend_method(self, "validate_#{method_name}_input!") do |*args|
|
170
|
+
(value, context) = args
|
171
|
+
context = " "+context if context
|
172
|
+
context ||= ""
|
173
|
+
send(validator, value, context)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def object_setter(klass, method_name, cast)
|
178
|
+
define_method("#{method_name}=") do |value|
|
179
|
+
validate_input(method_name, value)
|
180
|
+
if value.kind_of?(cast)
|
181
|
+
value = klass.new(value)
|
182
|
+
end
|
183
|
+
instance_variable_set("@#{method_name}", value)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def object_list_setter(klass, method_name)
|
188
|
+
define_method("#{method_name}=") do |value|
|
189
|
+
validate_input(method_name, value)
|
190
|
+
list = value.map do |member|
|
191
|
+
if member.kind_of?(Hash)
|
192
|
+
klass.new(member)
|
193
|
+
else
|
194
|
+
member
|
195
|
+
end
|
196
|
+
end
|
197
|
+
instance_variable_set("@#{method_name}", list)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def validate_string(method_name)
|
202
|
+
Core::MetaUtils.class_extend_method(self, :validate!) do
|
203
|
+
super()
|
204
|
+
raise "missing #{method_name}" unless send(method_name)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def validate_object(method_name)
|
209
|
+
Core::MetaUtils.class_extend_method(self, :validate!) do
|
210
|
+
super()
|
211
|
+
raise "missing #{method_name}" unless send(method_name)
|
212
|
+
send(method_name).validate!
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def validate_list(method_name)
|
217
|
+
Core::MetaUtils.class_extend_method(self, :validate!) do
|
218
|
+
super()
|
219
|
+
raise "missing #{method_name}" unless send(method_name)
|
220
|
+
send(method_name).each { |member| member.validate! }
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def body_xml_string_content(element_name, method_name)
|
225
|
+
add_xml_child(method_name) do |value|
|
226
|
+
normalized = REXML::Text.normalize(value.to_s)
|
227
|
+
"<#{element_name}>#{normalized}</#{element_name}>"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def body_xml_content(method_name)
|
232
|
+
add_xml_child(method_name) { |value| value.to_s }
|
233
|
+
end
|
234
|
+
|
235
|
+
def body_xml_list_content(list_element, method_name)
|
236
|
+
add_xml_child(method_name) do |list|
|
237
|
+
list_content = list.map { |member| member.to_s }.join
|
238
|
+
if list_content.empty?
|
239
|
+
"<#{list_element}/>"
|
240
|
+
else
|
241
|
+
"<#{list_element}>#{list_content}</#{list_element}>"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def add_xml_child(method_name)
|
247
|
+
Core::MetaUtils.class_extend_method(self, :body_xml) do
|
248
|
+
xml = super()
|
249
|
+
value = send(method_name)
|
250
|
+
xml += yield(value) if value
|
251
|
+
xml
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
def self.included(m)
|
258
|
+
m.extend(ClassMethods)
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# or in the "license" file accompanying this file. This file is
|
9
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
10
|
+
# ANY KIND, either express or implied. See the License for the specific
|
11
|
+
# language governing permissions and limitations under the License.
|
12
|
+
|
13
|
+
require 'rexml/document'
|
14
|
+
|
15
|
+
module MSS
|
16
|
+
class S3
|
17
|
+
|
18
|
+
# Provides a method to {Bucket} and {S3Object} that parses a wide
|
19
|
+
# range of ACL options.
|
20
|
+
# @api private
|
21
|
+
module ACLOptions
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
# @param [Symbol,String,Hash,AccessControlList] acl Accepts an ACL
|
26
|
+
# description in one of the following formats:
|
27
|
+
#
|
28
|
+
# ==== Canned ACL
|
29
|
+
#
|
30
|
+
# S3 supports a number of canned ACLs for buckets and
|
31
|
+
# objects. These include:
|
32
|
+
#
|
33
|
+
# * `:private`
|
34
|
+
# * `:public_read`
|
35
|
+
# * `:public_read_write`
|
36
|
+
# * `:authenticated_read`
|
37
|
+
# * `:bucket_owner_read` (object-only)
|
38
|
+
# * `:bucket_owner_full_control` (object-only)
|
39
|
+
# * `:log_delivery_write` (bucket-only)
|
40
|
+
#
|
41
|
+
# Here is an example of providing a canned ACL to a bucket:
|
42
|
+
#
|
43
|
+
# s3.buckets['bucket-name'].acl = :public_read
|
44
|
+
#
|
45
|
+
# ==== ACL Grant Hash
|
46
|
+
#
|
47
|
+
# You can provide a hash of grants. The hash is composed of grants (keys)
|
48
|
+
# and grantees (values). Accepted grant keys are:
|
49
|
+
#
|
50
|
+
# * `:grant_read`
|
51
|
+
# * `:grant_write`
|
52
|
+
# * `:grant_read_acp`
|
53
|
+
# * `:grant_write_acp`
|
54
|
+
# * `:grant_full_control`
|
55
|
+
#
|
56
|
+
# Grantee strings (values) should be formatted like some of the
|
57
|
+
# following examples:
|
58
|
+
#
|
59
|
+
# id="8a6925ce4adf588a4532142d3f74dd8c71fa124b1ddee97f21c32aa379004fef"
|
60
|
+
# uri="http://acs.amazonmss.com/groups/global/AllUsers"
|
61
|
+
#
|
62
|
+
# You can provide a comma delimited list of multiple grantees in a single
|
63
|
+
# string. Please note the use of quotes inside the grantee string.
|
64
|
+
# Here is a simple example:
|
65
|
+
#
|
66
|
+
# { :grant_full_control => "emailAddress=\"foo@bar.com\", id=\"abc..mno\"" }
|
67
|
+
#
|
68
|
+
# See the S3 API documentation for more information on formatting
|
69
|
+
# grants.
|
70
|
+
#
|
71
|
+
# ==== AcessControlList Object
|
72
|
+
#
|
73
|
+
# You can build an ACL using the {AccessControlList} class and
|
74
|
+
# pass this object.
|
75
|
+
#
|
76
|
+
# acl = MSS::S3::AccessControlList.new
|
77
|
+
# acl.grant(:full_control).to(:canonical_user_id => "8a6...fef")
|
78
|
+
# acl #=> this is acceptible
|
79
|
+
#
|
80
|
+
# ==== ACL XML String
|
81
|
+
#
|
82
|
+
# Lastly you can build your own ACL XML document and pass it as a string.
|
83
|
+
#
|
84
|
+
# <<-XML
|
85
|
+
# <AccessControlPolicy xmlns="http://s3.amazonmss.com/doc/2006-03-01/">
|
86
|
+
# <Owner>
|
87
|
+
# <ID>8a6...fef</ID>
|
88
|
+
# <DisplayName>owner-display-name</DisplayName>
|
89
|
+
# </Owner>
|
90
|
+
# <AccessControlList>
|
91
|
+
# <Grant>
|
92
|
+
# <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Canonical User">
|
93
|
+
# <ID>8a6...fef</ID>
|
94
|
+
# <DisplayName>owner-display-name</DisplayName>
|
95
|
+
# </Grantee>
|
96
|
+
# <Permission>FULL_CONTROL</Permission>
|
97
|
+
# </Grant>
|
98
|
+
# </AccessControlList>
|
99
|
+
# </AccessControlPolicy>
|
100
|
+
# XML
|
101
|
+
#
|
102
|
+
# @return [Hash] Returns a hash of options suitable for
|
103
|
+
# passing to {Client#put_bucket_acl} and {Client#put_object_acl}
|
104
|
+
# with a mixture of ACL options.
|
105
|
+
#
|
106
|
+
def acl_options acl
|
107
|
+
case acl
|
108
|
+
when Symbol
|
109
|
+
{ :acl => acl.to_s.tr('_', '-') }
|
110
|
+
when String
|
111
|
+
# Strings are either access control policies (xml strings)
|
112
|
+
# or they are canned acls
|
113
|
+
xml?(acl) ?
|
114
|
+
{ :access_control_policy => acl } :
|
115
|
+
{ :acl => acl }
|
116
|
+
when AccessControlList
|
117
|
+
{ :access_control_policy => acl.to_xml }
|
118
|
+
when Hash
|
119
|
+
# Hashes are either grant hashes or constructor args for an
|
120
|
+
# access control list (deprecated)
|
121
|
+
grant_hash?(acl) ?
|
122
|
+
format_grants(acl) :
|
123
|
+
{ :access_control_policy => AccessControlList.new(acl).to_xml }
|
124
|
+
else
|
125
|
+
# failed to parse the acl option
|
126
|
+
msg = "expected a canned ACL, AccessControlList object, ACL "
|
127
|
+
"XML string or a grants hash"
|
128
|
+
raise ArgumentError, msg
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param [Hash] acl_hash
|
133
|
+
# @return [Boolean] Retursn `true` if this hash is a hash of grants.
|
134
|
+
def grant_hash? acl_hash
|
135
|
+
grant_keys = [
|
136
|
+
:grant_read,
|
137
|
+
:grant_write,
|
138
|
+
:grant_read_acp,
|
139
|
+
:grant_write_acp,
|
140
|
+
:grant_full_control,
|
141
|
+
]
|
142
|
+
acl_hash.keys.all?{|key| grant_keys.include?(key) }
|
143
|
+
end
|
144
|
+
|
145
|
+
# @param [String] acl_string
|
146
|
+
# @return [Boolean] Returns `true` if this string is an xml document.
|
147
|
+
def xml? acl_string
|
148
|
+
begin
|
149
|
+
REXML::Document.new(acl_string).has_elements?
|
150
|
+
rescue
|
151
|
+
false
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# @param [Hash] acl_hash
|
156
|
+
# @return [Hash] Returns a hash of grant options suitable for
|
157
|
+
# passing to the various S3 client methods that accept ACL grants.
|
158
|
+
def format_grants acl_hash
|
159
|
+
grants = {}
|
160
|
+
acl_hash.each_pair do |grant,grantees|
|
161
|
+
grantees = [grantees] unless grantees.is_a?(Array)
|
162
|
+
grants[grant] = grantees.map{|g| format_grantee(g) }.join(', ')
|
163
|
+
end
|
164
|
+
grants
|
165
|
+
end
|
166
|
+
|
167
|
+
def format_grantee grantee
|
168
|
+
case grantee
|
169
|
+
when String then grantee
|
170
|
+
when Hash
|
171
|
+
|
172
|
+
if grantee.keys.count != 1
|
173
|
+
msg = "grantee hashes must have exactly 1 key"
|
174
|
+
raise ArgumentError, msg
|
175
|
+
end
|
176
|
+
|
177
|
+
# A granee hash looks like:
|
178
|
+
#
|
179
|
+
# { :id => 'abc...fec' }
|
180
|
+
# { :uri => 'http://abc.com/foo' }
|
181
|
+
#
|
182
|
+
# It needs to look like
|
183
|
+
#
|
184
|
+
# 'id="abc...fec"'
|
185
|
+
# 'uri="http://abc.com/foo"'
|
186
|
+
type, token = grantee.to_a.flatten
|
187
|
+
type = type.to_s.split('_').map{|part| ucfirst(part) }.join
|
188
|
+
"#{type[0,1].downcase}#{type[1..-1]}=\"#{token}\""
|
189
|
+
else
|
190
|
+
raise ArgumentError, "grantees must be a string or a hash"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def ucfirst str
|
195
|
+
str[0,1].upcase + str[1..-1]
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|