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
data/lib/mss/errors.rb
ADDED
@@ -0,0 +1,161 @@
|
|
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
|
+
module MSS
|
14
|
+
|
15
|
+
# # Errors
|
16
|
+
#
|
17
|
+
# There are two basic types of errors:
|
18
|
+
#
|
19
|
+
# * {ClientError}
|
20
|
+
# * {ServerError}
|
21
|
+
#
|
22
|
+
# ## Client Errors
|
23
|
+
#
|
24
|
+
# Errors in the three and four hundreds are client errors ({ClientError}).
|
25
|
+
# A client error should not be resent without changes. The body of the
|
26
|
+
# http response (the error #message) should give more information about
|
27
|
+
# the nature of the problem.
|
28
|
+
#
|
29
|
+
# ## Server Errors
|
30
|
+
#
|
31
|
+
# A 500 level error typically indicates the service is having an issue.
|
32
|
+
#
|
33
|
+
# Requests that generate service errors are automatically retried with
|
34
|
+
# an exponential backoff. If the service still fails to respond with
|
35
|
+
# a 200 after 3 retries the error is raised.
|
36
|
+
#
|
37
|
+
module Errors
|
38
|
+
|
39
|
+
# Base class for all errors returned by the service.
|
40
|
+
class Base < StandardError
|
41
|
+
|
42
|
+
# @overload new(error_message)
|
43
|
+
# @param [String] error_message The body of the error message
|
44
|
+
#
|
45
|
+
# @overload new(http_request, http_response, code = nil, message = nil)
|
46
|
+
# @param [Http::Request] http_request
|
47
|
+
# @param [Http::Response] http_response
|
48
|
+
# @param [String] code (nil)
|
49
|
+
# @param [String] message (nil)
|
50
|
+
#
|
51
|
+
def initialize req = nil, resp = nil, code = nil, message = nil
|
52
|
+
if req.is_a?(String) or req.nil?
|
53
|
+
super(req)
|
54
|
+
else
|
55
|
+
@http_request = req
|
56
|
+
@http_response = resp
|
57
|
+
@code = code
|
58
|
+
include_error_type
|
59
|
+
super(message || http_response.body)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [String] The response code given by the service.
|
64
|
+
attr_reader :code
|
65
|
+
|
66
|
+
# @return [Http::Request] The low level http request that caused the
|
67
|
+
# error to be raised.
|
68
|
+
attr_reader :http_request
|
69
|
+
|
70
|
+
# @return [Http::Response] The low level http response from the service
|
71
|
+
# that wrapped the service error.
|
72
|
+
attr_reader :http_response
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
# Extends the error object with {ServerError} or {ClientError}.
|
77
|
+
# This indicates if the request should be retried (server errors)
|
78
|
+
# or not (client errors).
|
79
|
+
def include_error_type
|
80
|
+
if http_response.status >= 500
|
81
|
+
extend ServerError
|
82
|
+
else
|
83
|
+
extend ClientError
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# Provides the ability to instantiate instances of {ServerError} and
|
90
|
+
# {ClientError}.
|
91
|
+
# @api private
|
92
|
+
module ExceptionMixinClassMethods
|
93
|
+
def new(*args)
|
94
|
+
e = Base.new(*args)
|
95
|
+
e.extend(self)
|
96
|
+
e
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Raised when an error occurs as a result of bad client
|
101
|
+
# behavior, most commonly when the parameters passed to a method
|
102
|
+
# are somehow invalid. Other common cases:
|
103
|
+
#
|
104
|
+
# * Throttling errors
|
105
|
+
# * Bad credentials
|
106
|
+
# * No permission to do the requested operation
|
107
|
+
# * Limits exceeded (e.g. too many buckets)
|
108
|
+
#
|
109
|
+
module ClientError
|
110
|
+
extend ExceptionMixinClassMethods
|
111
|
+
end
|
112
|
+
|
113
|
+
# Raised when an MSS service is unable to handle the request. These
|
114
|
+
# are automatically retired. If after 3 retries the request is still
|
115
|
+
# failing, then the error is raised.
|
116
|
+
module ServerError
|
117
|
+
extend ExceptionMixinClassMethods
|
118
|
+
end
|
119
|
+
|
120
|
+
# Raised when MSS credentials could not be found.
|
121
|
+
class MissingCredentialsError < StandardError
|
122
|
+
|
123
|
+
def initialize msg = nil
|
124
|
+
msg ||= <<-MSG
|
125
|
+
|
126
|
+
Missing Credentials.
|
127
|
+
|
128
|
+
Unable to find MSS credentials. You can configure your MSS credentials
|
129
|
+
a few different ways:
|
130
|
+
|
131
|
+
* Call MSS.config with :access_key_id and :secret_access_key
|
132
|
+
|
133
|
+
* Export MSS_ACCESS_KEY_ID and MSS_SECRET_ACCESS_KEY to ENV
|
134
|
+
|
135
|
+
* On EC2 you can run instances with an IAM instance profile and credentials
|
136
|
+
will be auto loaded from the instance metadata service on those
|
137
|
+
instances.
|
138
|
+
|
139
|
+
* Call MSS.config with :credential_provider. A credential provider should
|
140
|
+
either include MSS::Core::CredentialProviders::Provider or respond to
|
141
|
+
the same public methods.
|
142
|
+
|
143
|
+
= Ruby on Rails
|
144
|
+
|
145
|
+
In a Ruby on Rails application you may also specify your credentials in
|
146
|
+
the following ways:
|
147
|
+
|
148
|
+
* Via a config initializer script using any of the methods mentioned above
|
149
|
+
(e.g. RAILS_ROOT/config/initializers/mss-sdk.rb).
|
150
|
+
|
151
|
+
* Via a yaml configuration file located at RAILS_ROOT/config/mss.yml.
|
152
|
+
This file should be formated like the default RAILS_ROOT/config/database.yml
|
153
|
+
file.
|
154
|
+
|
155
|
+
MSG
|
156
|
+
super(msg)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
data/lib/mss/rails.rb
ADDED
@@ -0,0 +1,194 @@
|
|
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 'yaml'
|
14
|
+
|
15
|
+
module MSS
|
16
|
+
|
17
|
+
if Object.const_defined?(:Rails) and Rails.const_defined?(:Railtie)
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
class Railtie < Rails::Railtie
|
21
|
+
|
22
|
+
# configure our plugin on boot. other extension points such
|
23
|
+
# as configuration, rake tasks, etc, are also available
|
24
|
+
initializer "mss-sdk.initialize" do |app|
|
25
|
+
MSS::Rails.setup
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
# A handful of useful Rails integration methods.
|
32
|
+
#
|
33
|
+
# If you require this gem inside a Rails application (via config.gem
|
34
|
+
# for rails 2 and bundler for rails 3) then {setup} is called
|
35
|
+
# automatically.
|
36
|
+
module Rails
|
37
|
+
|
38
|
+
# Adds extra functionality to Rails.
|
39
|
+
#
|
40
|
+
# Normally this method is invoked automatically when you require this
|
41
|
+
# gem in a Rails Application:
|
42
|
+
#
|
43
|
+
# Rails 3+ (RAILS_ROOT/Gemfile)
|
44
|
+
#
|
45
|
+
# gem 'mss-sdk'
|
46
|
+
#
|
47
|
+
# Rails 2.1 - 2.3 (RAILS_ROOT/config/environment.rb)
|
48
|
+
#
|
49
|
+
# config.gem 'mss-sdk'
|
50
|
+
#
|
51
|
+
# @return [nil]
|
52
|
+
def self.setup
|
53
|
+
load_yaml_config
|
54
|
+
add_action_mailer_delivery_method
|
55
|
+
log_to_rails_logger
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# Loads MSS configuration options from `RAILS_ROOT/config/mss.yml`.
|
60
|
+
#
|
61
|
+
# This configuration file is optional. You can omit this file and instead
|
62
|
+
# use ruby to configure MSS inside a configuration initialization script
|
63
|
+
# (e.g. RAILS_ROOT/config/intializers/mss.rb).
|
64
|
+
#
|
65
|
+
# If you have a yaml configuration file it should be formatted like the
|
66
|
+
# standard `database.yml` file in a Rails application. This means there
|
67
|
+
# should be one section for Rails environment:
|
68
|
+
#
|
69
|
+
# development:
|
70
|
+
# access_key_id: YOUR_ACCESS_KEY_ID
|
71
|
+
# secret_access_key: YOUR_SECRET_ACCESS_KEY
|
72
|
+
# simple_db_consistent_reads: false
|
73
|
+
#
|
74
|
+
# production:
|
75
|
+
# access_key_id: YOUR_ACCESS_KEY_ID
|
76
|
+
# secret_access_key: YOUR_SECRET_ACCESS_KEY
|
77
|
+
# simple_db_consistent_reads: true
|
78
|
+
#
|
79
|
+
# You should also consider DRYing up your configuration file using
|
80
|
+
# YAML references:
|
81
|
+
#
|
82
|
+
# development:
|
83
|
+
# access_key_id: YOUR_ACCESS_KEY_ID
|
84
|
+
# secret_access_key: YOUR_SECRET_ACCESS_KEY
|
85
|
+
# simple_db_consistent_reads: false
|
86
|
+
#
|
87
|
+
# production:
|
88
|
+
# <<: *development
|
89
|
+
# simple_db_consistent_reads: true
|
90
|
+
#
|
91
|
+
# The yaml file will also be ERB parsed so you can use ruby inside of it:
|
92
|
+
#
|
93
|
+
# development:
|
94
|
+
# access_key_id: YOUR_ACCESS_KEY_ID
|
95
|
+
# secret_access_key: <%= read_secret_from_a_secure_location %>
|
96
|
+
# simple_db_consistent_reads: false
|
97
|
+
#
|
98
|
+
# production:
|
99
|
+
# <<: *development
|
100
|
+
# simple_db_consistent_reads: true
|
101
|
+
#
|
102
|
+
def self.load_yaml_config
|
103
|
+
|
104
|
+
path = Pathname.new("#{rails_root}/config/mss.yml")
|
105
|
+
|
106
|
+
if File.exist?(path)
|
107
|
+
cfg = YAML::load(ERB.new(File.read(path)).result)
|
108
|
+
unless cfg[rails_env]
|
109
|
+
raise "config/mss.yml is missing a section for `#{rails_env}`"
|
110
|
+
end
|
111
|
+
MSS.config(cfg[rails_env])
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
# Adds a delivery method to ActionMailer that uses
|
117
|
+
# {MSS::SimpleEmailService}.
|
118
|
+
#
|
119
|
+
# Once you have an SES delivery method you can configure Rails to
|
120
|
+
# use this for ActionMailer in your environment configuration
|
121
|
+
# (e.g. RAILS_ROOT/config/environments/production.rb)
|
122
|
+
#
|
123
|
+
# config.action_mailer.delivery_method = :amazon_ses
|
124
|
+
#
|
125
|
+
# ### Defaults
|
126
|
+
#
|
127
|
+
# Normally you don't need to call this method. By default a delivery method
|
128
|
+
# named `:amazon_ses` is added to ActionMailer::Base. This delivery method
|
129
|
+
# uses your default configuration (#{MSS.config}).
|
130
|
+
#
|
131
|
+
# ### Custom SES Options
|
132
|
+
#
|
133
|
+
# If you need to supply configuration values for SES that are different than
|
134
|
+
# those in {MSS.config} then you can pass those options:
|
135
|
+
#
|
136
|
+
# MSS::Rails.add_action_mailer_delivery_method(:ses, custom_options)
|
137
|
+
#
|
138
|
+
# @param [Symbol] name (:amazon_ses) The name of the delivery
|
139
|
+
# method. The name used here should be the same as you set in
|
140
|
+
# your environment config. If you name the delivery method
|
141
|
+
# `:amazon_ses` then you could do something like this in your
|
142
|
+
# config/environments/ENV.rb file:
|
143
|
+
#
|
144
|
+
# config.action_mailer.delivery_method = :amazon_ses
|
145
|
+
#
|
146
|
+
# @param [Hash] options A hash of options that are passes to
|
147
|
+
# {MSS::SimpleEmailService#new} before delivering email.
|
148
|
+
#
|
149
|
+
# @return [nil]
|
150
|
+
#
|
151
|
+
def self.add_action_mailer_delivery_method name = :amazon_ses, options = {}
|
152
|
+
|
153
|
+
if ::Rails.version.to_s >= '3.0'
|
154
|
+
ActiveSupport.on_load(:action_mailer) do
|
155
|
+
self.add_delivery_method(name, MSS::SimpleEmailService, options)
|
156
|
+
end
|
157
|
+
elsif defined?(::ActionMailer)
|
158
|
+
amb = ::ActionMailer::Base
|
159
|
+
amb.send(:define_method, "perform_delivery_#{name}") do |mail|
|
160
|
+
MSS::SimpleEmailService.new(options).send_raw_email(mail)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
nil
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
# Configures MSS to log to the Rails default logger.
|
169
|
+
# @return [nil]
|
170
|
+
def self.log_to_rails_logger
|
171
|
+
MSS.config(:logger => rails_logger)
|
172
|
+
nil
|
173
|
+
end
|
174
|
+
|
175
|
+
# @api private
|
176
|
+
protected
|
177
|
+
def self.rails_env
|
178
|
+
::Rails.respond_to?(:env) ? ::Rails.env : RAILS_ENV
|
179
|
+
end
|
180
|
+
|
181
|
+
# @api private
|
182
|
+
protected
|
183
|
+
def self.rails_root
|
184
|
+
::Rails.respond_to?(:root) ? ::Rails.root.to_s : RAILS_ROOT
|
185
|
+
end
|
186
|
+
|
187
|
+
# @api private
|
188
|
+
protected
|
189
|
+
def self.rails_logger
|
190
|
+
::Rails.respond_to?(:logger) ? ::Rails.logger : ::RAILS_DEFAULT_LOGGER
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,262 @@
|
|
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
|
+
module MSS
|
14
|
+
class S3
|
15
|
+
|
16
|
+
# Represents an access control list for S3 objects and buckets. For example:
|
17
|
+
#
|
18
|
+
# acl = AccessControlList.new
|
19
|
+
# acl.grant(:full_control).
|
20
|
+
# to(:canonical_user_id => "8a6925ce4adf588a4f21c32aa379004fef")
|
21
|
+
# acl.to_xml # => '<AccessControlPolicy>...'
|
22
|
+
#
|
23
|
+
# You can also construct an AccessControlList from a hash:
|
24
|
+
#
|
25
|
+
# AccessControlList.new(
|
26
|
+
# :owner => { :id => "8a6925ce4adf588a4f21c32aa379004fef" },
|
27
|
+
# :grants => [{
|
28
|
+
# :grantee => { :canonical_user_id => "8a6925ce4adf588a4f21c32aa379004fef" },
|
29
|
+
# :permission => :full_control,
|
30
|
+
# }]
|
31
|
+
# )
|
32
|
+
#
|
33
|
+
# @see ACLObject
|
34
|
+
#
|
35
|
+
# @attr [AccessControlList::Owner] owner The owner of the access
|
36
|
+
# control list. You can set this as a hash, for example:
|
37
|
+
# acl.owner = { :id => '8a6925ce4adf588a4f21c32aa379004fef' }
|
38
|
+
# This attribute is required when setting an ACL.
|
39
|
+
#
|
40
|
+
# @attr [list of AccessControlList::Grant] grants The list of
|
41
|
+
# grants. You can set this as a list of hashes, for example:
|
42
|
+
#
|
43
|
+
# acl.grants = [{
|
44
|
+
# :grantee => { :canonical_user_id => "8a6925ce4adf588a4f21c32aa379004fef" },
|
45
|
+
# :permission => :full_control,
|
46
|
+
# }]
|
47
|
+
class AccessControlList
|
48
|
+
|
49
|
+
# Represents an ACL owner. In the default ACL, this is the
|
50
|
+
# bucket owner.
|
51
|
+
#
|
52
|
+
# @attr [String] id The canonical user ID of the ACL owner.
|
53
|
+
# This attribute is required when setting an ACL.
|
54
|
+
#
|
55
|
+
# @attr [String] display_name The display name of the ACL
|
56
|
+
# owner. This value is ignored when setting an ACL.
|
57
|
+
class Owner
|
58
|
+
include ACLObject
|
59
|
+
|
60
|
+
string_attr "ID", :required => true
|
61
|
+
string_attr "DisplayName"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Represents a user who is granted some kind of permission
|
65
|
+
# through a Grant. There are three ways to specify a grantee:
|
66
|
+
#
|
67
|
+
# * You can specify the canonical user ID, for example. When
|
68
|
+
# you read an ACL from S3, all grantees will be identified
|
69
|
+
# this way, and the display_name attribute will also be provided.
|
70
|
+
#
|
71
|
+
# Grantee.new(:canonical_user_id => "8a6925ce4adf588a4f21c32aa379004fef")
|
72
|
+
#
|
73
|
+
# * You can specify the e-mail address of an MSS customer, for example:
|
74
|
+
#
|
75
|
+
# Grantee.new(:amazon_customer_email => 'foo@example.com')
|
76
|
+
#
|
77
|
+
# * You can specify a group URI, for example:
|
78
|
+
#
|
79
|
+
# Grantee.new(:group_uri => 'http://acs.amazonmss.com/groups/global/AllUsers')
|
80
|
+
#
|
81
|
+
# For more details about group URIs, see:
|
82
|
+
#
|
83
|
+
# When constructing a grantee, you must provide a value for
|
84
|
+
# exactly one of the following attributes:
|
85
|
+
#
|
86
|
+
# * `amazon_customer_email`
|
87
|
+
# * `canonical_user_id`
|
88
|
+
# * `group_uri`
|
89
|
+
#
|
90
|
+
# @attr [String] amazon_customer_email The e-mail address of
|
91
|
+
# an MSS customer.
|
92
|
+
#
|
93
|
+
# @attr [String] canonical_user_id The canonical user ID of an
|
94
|
+
# MSS customer.
|
95
|
+
#
|
96
|
+
# @attr [String] group_uri A URI that identifies a particular
|
97
|
+
# group of users.
|
98
|
+
#
|
99
|
+
# @attr [String] display_name The display name associated with
|
100
|
+
# the grantee. This is provided by S3 when reading an ACL.
|
101
|
+
class Grantee
|
102
|
+
include ACLObject
|
103
|
+
|
104
|
+
SIGNAL_ATTRIBUTES = [
|
105
|
+
:amazon_customer_email,
|
106
|
+
:canonical_user_id,
|
107
|
+
:group_uri,
|
108
|
+
:uri,
|
109
|
+
]
|
110
|
+
|
111
|
+
string_attr "EmailAddress", :method_name => "amazon_customer_email"
|
112
|
+
string_attr "ID", :method_name => "canonical_user_id"
|
113
|
+
string_attr "URI", :method_name => "group_uri"
|
114
|
+
string_attr "URI", :method_name => "uri"
|
115
|
+
string_attr "DisplayName"
|
116
|
+
|
117
|
+
# (see ACLObject#validate!)
|
118
|
+
def validate!
|
119
|
+
attr = signal_attribute
|
120
|
+
raise "missing amazon_customer_email, canonical_user_id, "+
|
121
|
+
"or group_uri" unless attr
|
122
|
+
raise "display_name is invalid with #{attr}" if
|
123
|
+
attr != :canonical_user_id and display_name
|
124
|
+
end
|
125
|
+
|
126
|
+
# @api private
|
127
|
+
def stag
|
128
|
+
if attr = signal_attribute
|
129
|
+
super + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
|
130
|
+
" xsi:type=\"#{type_for_attr(attr)}\""
|
131
|
+
else
|
132
|
+
super
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# @api private
|
137
|
+
def signal_attribute
|
138
|
+
SIGNAL_ATTRIBUTES.find { |att| send(att) }
|
139
|
+
end
|
140
|
+
|
141
|
+
# @api private
|
142
|
+
def type_for_attr(attr)
|
143
|
+
{
|
144
|
+
:amazon_customer_email => "AmazonCustomerByEmail",
|
145
|
+
:canonical_user_id => "CanonicalUser",
|
146
|
+
:group_uri => "Group",
|
147
|
+
:uri => "Group",
|
148
|
+
}[attr]
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
# Represents the permission being granted in a Grant object.
|
154
|
+
# Typically you will not need to construct an instance of this
|
155
|
+
# class directly.
|
156
|
+
# @see Grant#permission
|
157
|
+
class Permission
|
158
|
+
include ACLObject
|
159
|
+
|
160
|
+
# The permission expressed as a symbol following Ruby
|
161
|
+
# conventions. For example, S3's FULL_CONTROL permission
|
162
|
+
# will be returned as `:full_control`.
|
163
|
+
attr_reader :name
|
164
|
+
|
165
|
+
# @api private
|
166
|
+
def initialize(name)
|
167
|
+
raise "expected string or symbol" unless
|
168
|
+
name.respond_to?(:to_str) or name.respond_to?(:to_sym)
|
169
|
+
@name = name.to_sym
|
170
|
+
end
|
171
|
+
|
172
|
+
def body_xml
|
173
|
+
name.to_s.upcase
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
# Represents a single grant in an ACL. Both `grantee` and
|
179
|
+
# `permission` are required for each grant when setting an
|
180
|
+
# ACL.
|
181
|
+
#
|
182
|
+
# See
|
183
|
+
# for more information on how grantees and permissions are
|
184
|
+
# interpreted by S3.
|
185
|
+
#
|
186
|
+
# @attr [Grantee] grantee The user or users who are granted
|
187
|
+
# access according to this grant. You can specify this as a
|
188
|
+
# hash:
|
189
|
+
#
|
190
|
+
# grant.grantee = { :amazon_customer_email => "foo@example.com" }
|
191
|
+
#
|
192
|
+
# @attr [Permission or Symbol] permission The type of
|
193
|
+
# permission that is granted by this grant. Valid values are:
|
194
|
+
# * `:read`
|
195
|
+
# * `:write`
|
196
|
+
# * `:read_acp`
|
197
|
+
# * `:write_acp`
|
198
|
+
# * `:full_control`
|
199
|
+
class Grant
|
200
|
+
|
201
|
+
include ACLObject
|
202
|
+
|
203
|
+
object_attr Grantee, :required => true
|
204
|
+
object_attr Permission, :required => true, :cast => Symbol
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
include ACLObject
|
209
|
+
|
210
|
+
# @api private
|
211
|
+
def stag
|
212
|
+
super()+" xmlns=\"http://s3.amazonmss.com/doc/2006-03-01/\""
|
213
|
+
end
|
214
|
+
|
215
|
+
# @api private
|
216
|
+
def element_name
|
217
|
+
"AccessControlPolicy"
|
218
|
+
end
|
219
|
+
|
220
|
+
class GrantBuilder
|
221
|
+
|
222
|
+
# @api private
|
223
|
+
def initialize(acl, grant)
|
224
|
+
@acl = acl
|
225
|
+
@grant = grant
|
226
|
+
end
|
227
|
+
|
228
|
+
# Specifies the grantee.
|
229
|
+
#
|
230
|
+
# @param [Grantee or Hash] grantee A Grantee object or hash;
|
231
|
+
# for example:
|
232
|
+
#
|
233
|
+
# acl.grant(:full_control).to(:amazon_customer_email => "foo@example.com")
|
234
|
+
def to(grantee)
|
235
|
+
@grant.grantee = grantee
|
236
|
+
@acl.grants << @grant
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
# Convenience method for constructing a new grant and adding
|
242
|
+
# it to the ACL.
|
243
|
+
#
|
244
|
+
# @example
|
245
|
+
#
|
246
|
+
# acl.grants.size # => 0
|
247
|
+
# acl.grant(:full_control).to(:canonical_user_id => "8a6925ce4adf588a4f21c32aa379004fef")
|
248
|
+
# acl.grants.size # => 1
|
249
|
+
#
|
250
|
+
# @return [GrantBuilder]
|
251
|
+
def grant(permission)
|
252
|
+
GrantBuilder.new(self, Grant.new(:permission => permission))
|
253
|
+
end
|
254
|
+
|
255
|
+
object_attr Owner, :required => true
|
256
|
+
object_list_attr("AccessControlList", Grant,
|
257
|
+
:required => true, :method_name => :grants)
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
end
|