s33r 0.4.2 → 0.5
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.
- data/examples/cli/instant_download_server.rb +88 -0
- data/examples/cli/s3cli.rb +31 -52
- data/examples/cli/simple.rb +16 -6
- data/examples/fores33r/app/controllers/browser_controller.rb +12 -10
- data/examples/fores33r/app/helpers/application_helper.rb +2 -1
- data/examples/fores33r/app/views/browser/_upload.rhtml +1 -1
- data/examples/fores33r/app/views/browser/index.rhtml +4 -4
- data/examples/fores33r/config/environment.rb +5 -3
- data/examples/fores33r/log/development.log +2259 -0
- data/examples/fores33r/log/mongrel.log +59 -0
- data/examples/s3.yaml +2 -6
- data/lib/s33r/bucket.rb +103 -0
- data/lib/s33r/bucket_listing.rb +33 -76
- data/lib/s33r/client.rb +305 -446
- data/lib/s33r/networking.rb +197 -0
- data/lib/s33r/s33r_exception.rb +29 -18
- data/lib/s33r/s33r_http.rb +36 -18
- data/lib/s33r/s3_acl.rb +32 -52
- data/lib/s33r/s3_logging.rb +117 -0
- data/lib/s33r/s3_obj.rb +124 -69
- data/lib/s33r/utility.rb +447 -0
- data/test/cases/spec_acl.rb +10 -40
- data/test/cases/spec_bucket_listing.rb +12 -32
- data/test/cases/spec_logging.rb +47 -0
- data/test/cases/spec_networking.rb +11 -0
- data/test/cases/spec_s3_object.rb +44 -5
- data/test/cases/spec_utility.rb +264 -0
- data/test/files/acl.xml +0 -6
- data/test/files/config.yaml +5 -0
- data/test/files/logging_status_disabled.xml +3 -0
- data/test/files/logging_status_enabled.xml +7 -0
- data/test/test_setup.rb +7 -2
- metadata +16 -94
- data/examples/cli/acl_x.rb +0 -41
- data/examples/cli/logging_x.rb +0 -20
- data/examples/fores33r/README +0 -183
- data/html/classes/MIME.html +0 -120
- data/html/classes/MIME/InvalidContentType.html +0 -119
- data/html/classes/MIME/Type.html +0 -1173
- data/html/classes/MIME/Types.html +0 -566
- data/html/classes/Net.html +0 -108
- data/html/classes/Net/HTTPGenericRequest.html +0 -233
- data/html/classes/Net/HTTPResponse.html +0 -271
- data/html/classes/S33r.html +0 -986
- data/html/classes/S33r/BucketListing.html +0 -434
- data/html/classes/S33r/Client.html +0 -1575
- data/html/classes/S33r/LoggingResource.html +0 -222
- data/html/classes/S33r/NamedBucket.html +0 -693
- data/html/classes/S33r/OrderlyXmlMarkup.html +0 -165
- data/html/classes/S33r/S33rException.html +0 -124
- data/html/classes/S33r/S33rException/BucketListingMaxKeysError.html +0 -111
- data/html/classes/S33r/S33rException/BucketNotLogTargetable.html +0 -119
- data/html/classes/S33r/S33rException/InvalidBucketListing.html +0 -111
- data/html/classes/S33r/S33rException/InvalidPermission.html +0 -111
- data/html/classes/S33r/S33rException/InvalidS3GroupType.html +0 -111
- data/html/classes/S33r/S33rException/MalformedBucketName.html +0 -111
- data/html/classes/S33r/S33rException/MethodNotAvailable.html +0 -111
- data/html/classes/S33r/S33rException/MissingBucketName.html +0 -111
- data/html/classes/S33r/S33rException/MissingRequiredHeaders.html +0 -111
- data/html/classes/S33r/S33rException/MissingResource.html +0 -111
- data/html/classes/S33r/S33rException/S3FallenOver.html +0 -111
- data/html/classes/S33r/S33rException/TryingToPutEmptyResource.html +0 -117
- data/html/classes/S33r/S33rException/UnsupportedCannedACL.html +0 -111
- data/html/classes/S33r/S33rException/UnsupportedHTTPMethod.html +0 -111
- data/html/classes/S33r/S3ACL.html +0 -125
- data/html/classes/S33r/S3ACL/ACLDoc.html +0 -521
- data/html/classes/S33r/S3ACL/AmazonCustomer.html +0 -168
- data/html/classes/S33r/S3ACL/CanonicalUser.html +0 -212
- data/html/classes/S33r/S3ACL/Grant.html +0 -403
- data/html/classes/S33r/S3ACL/Grantee.html +0 -239
- data/html/classes/S33r/S3ACL/Group.html +0 -178
- data/html/classes/S33r/S3Object.html +0 -618
- data/html/classes/S33r/Sync.html +0 -152
- data/html/classes/XML.html +0 -202
- data/html/classes/XML/Document.html +0 -125
- data/html/classes/XML/Node.html +0 -124
- data/html/created.rid +0 -1
- data/html/files/CHANGELOG.html +0 -107
- data/html/files/MIT-LICENSE.html +0 -129
- data/html/files/README_txt.html +0 -259
- data/html/files/lib/s33r/bucket_listing_rb.html +0 -101
- data/html/files/lib/s33r/builder_rb.html +0 -108
- data/html/files/lib/s33r/client_rb.html +0 -111
- data/html/files/lib/s33r/core_rb.html +0 -113
- data/html/files/lib/s33r/libxml_extensions_rb.html +0 -101
- data/html/files/lib/s33r/libxml_loader_rb.html +0 -109
- data/html/files/lib/s33r/logging_rb.html +0 -108
- data/html/files/lib/s33r/mimetypes_rb.html +0 -120
- data/html/files/lib/s33r/named_bucket_rb.html +0 -101
- data/html/files/lib/s33r/s33r_exception_rb.html +0 -101
- data/html/files/lib/s33r/s33r_http_rb.html +0 -108
- data/html/files/lib/s33r/s3_acl_rb.html +0 -108
- data/html/files/lib/s33r/s3_obj_rb.html +0 -108
- data/html/files/lib/s33r/sync_rb.html +0 -101
- data/html/files/lib/s33r_rb.html +0 -101
- data/html/fr_class_index.html +0 -66
- data/html/fr_file_index.html +0 -44
- data/html/fr_method_index.html +0 -183
- data/html/index.html +0 -24
- data/html/rdoc-style.css +0 -208
- data/lib/s33r/core.rb +0 -296
- data/lib/s33r/logging.rb +0 -43
- data/lib/s33r/named_bucket.rb +0 -148
- data/lib/s33r/sync.rb +0 -13
- data/test/cases/spec_all_buckets.rb +0 -28
- data/test/cases/spec_client.rb +0 -101
- data/test/cases/spec_core.rb +0 -128
- data/test/cases/spec_namedbucket.rb +0 -46
- data/test/cases/spec_sync.rb +0 -34
- data/test/files/all_buckets.xml +0 -21
- data/test/files/client_config.yml +0 -5
- data/test/files/namedbucket_config.yml +0 -8
- data/test/files/namedbucket_config2.yml +0 -8
- data/test/test_bucket_setup.rb +0 -41
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'openssl'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'net/https'
|
|
5
|
+
require 'stringio'
|
|
6
|
+
|
|
7
|
+
base = File.dirname(__FILE__)
|
|
8
|
+
require File.join(base, 's33r_exception')
|
|
9
|
+
require File.join(base, 's33r_http')
|
|
10
|
+
require File.join(base, 'utility')
|
|
11
|
+
|
|
12
|
+
# Core functionality for managing HTTP requests to S3.
|
|
13
|
+
module S33r
|
|
14
|
+
module Networking
|
|
15
|
+
include S3Exception
|
|
16
|
+
include Net
|
|
17
|
+
|
|
18
|
+
#-- These are specific to the mechanics of the HTTP request.
|
|
19
|
+
|
|
20
|
+
# Net::HTTP instance.
|
|
21
|
+
attr_accessor :client
|
|
22
|
+
|
|
23
|
+
# Are HTTP connections persistent?
|
|
24
|
+
attr_accessor :persistent
|
|
25
|
+
|
|
26
|
+
# Default chunk size for connections.
|
|
27
|
+
attr_accessor :chunk_size
|
|
28
|
+
|
|
29
|
+
# Should requests be dumped?
|
|
30
|
+
attr_accessor :dump_requests
|
|
31
|
+
|
|
32
|
+
# The last response received by the client.
|
|
33
|
+
attr_reader :last_response
|
|
34
|
+
|
|
35
|
+
# Get default options to use on every response.
|
|
36
|
+
def request_defaults
|
|
37
|
+
@request_defaults || {}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Set the defaults.
|
|
41
|
+
def request_defaults=(options={})
|
|
42
|
+
@request_defaults = options
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Send a request over the wire.
|
|
46
|
+
#
|
|
47
|
+
# This method streams +data+ if it responds to the +stat+ method
|
|
48
|
+
# (as file handles do).
|
|
49
|
+
#
|
|
50
|
+
# Keys for +headers+ should be strings (e.g. 'Content-Type').
|
|
51
|
+
#
|
|
52
|
+
# +url_options+ is a standard set of options acceptable to s3_url;
|
|
53
|
+
# if any options aren't set, they are set using the +request_defaults+ method
|
|
54
|
+
# (options passed in here override defaults).
|
|
55
|
+
#
|
|
56
|
+
# You can also pass <tt>:authenticated => false</tt> if you want to visit a
|
|
57
|
+
# public URL here; otherwise, an Authorization header is generated and sent. If the client
|
|
58
|
+
# doesn't have an access key or secret access key specified, however, trying to create
|
|
59
|
+
# an access key will result in an error being raised.
|
|
60
|
+
#
|
|
61
|
+
# Returns a Net::HTTPResponse instance.
|
|
62
|
+
def do_request(method, url_options={}, data=nil, headers={})
|
|
63
|
+
# Use the default settings only if not specified in url_options.
|
|
64
|
+
url_options = request_defaults.merge(url_options)
|
|
65
|
+
|
|
66
|
+
# Get the URL.
|
|
67
|
+
url = s3_url(url_options)
|
|
68
|
+
uri = URI(url)
|
|
69
|
+
|
|
70
|
+
# Bar any except the allowed methods.
|
|
71
|
+
raise MethodNotAllowed, "The #{method} HTTP method is not supported" unless METHOD_VERBS.include?(method)
|
|
72
|
+
|
|
73
|
+
# Get a requester.
|
|
74
|
+
path = uri.path
|
|
75
|
+
path += "?" + uri.query if uri.query
|
|
76
|
+
req = eval("HTTP::" + method[0,1].upcase + method[1..-1].downcase + ".new('#{path}')")
|
|
77
|
+
|
|
78
|
+
req.chunk_size = chunk_size || DEFAULT_CHUNK_SIZE
|
|
79
|
+
|
|
80
|
+
# Add the S3 headers which are always required.
|
|
81
|
+
headers.merge!(default_headers(headers))
|
|
82
|
+
|
|
83
|
+
# Headers for canned ACL
|
|
84
|
+
headers.merge! canned_acl_header(url_options[:canned_acl]) if 'PUT' == method
|
|
85
|
+
|
|
86
|
+
# Generate the S3 authorization header if the client has
|
|
87
|
+
# the appropriate instance variable getters.
|
|
88
|
+
unless (false == url_options[:authenticated])
|
|
89
|
+
headers['Authorization'] = generate_auth_header_value(method, path, headers,
|
|
90
|
+
url_options[:access], url_options[:secret])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Insert the headers into the request object.
|
|
94
|
+
headers.each do |key, value|
|
|
95
|
+
req[key] = value
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Add data to the request as a stream.
|
|
99
|
+
if req.request_body_permitted?
|
|
100
|
+
# For streaming files; NB Content-Length will be set by Net::HTTP
|
|
101
|
+
# for character-based data: this section of is only used
|
|
102
|
+
# when reading directly from a file.
|
|
103
|
+
if data.respond_to?(:stat)
|
|
104
|
+
length = data.stat.size
|
|
105
|
+
# Strings can be streamed too.
|
|
106
|
+
elsif data.is_a?(String)
|
|
107
|
+
length = data.length
|
|
108
|
+
data = StringIO.new(data)
|
|
109
|
+
else
|
|
110
|
+
length = 0
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Data can be streamed if it responds to the read method.
|
|
114
|
+
if data.respond_to?(:read)
|
|
115
|
+
req.body_stream = data
|
|
116
|
+
req['Content-Length'] = length.to_s
|
|
117
|
+
data = nil
|
|
118
|
+
end
|
|
119
|
+
else
|
|
120
|
+
data = nil
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
puts req.to_s if @dump_requests
|
|
124
|
+
|
|
125
|
+
# Set up the request.
|
|
126
|
+
### <snip> start shameless stealing from Marcel Molina
|
|
127
|
+
request_runner = Proc.new do
|
|
128
|
+
response = @client.request(req, data)
|
|
129
|
+
|
|
130
|
+
# Add some nice messages to the response (like the S3 error
|
|
131
|
+
# message if it occurred).
|
|
132
|
+
response.conveniencify(method)
|
|
133
|
+
@last_response = response
|
|
134
|
+
|
|
135
|
+
return response
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Get a client instance.
|
|
139
|
+
init_client(uri)
|
|
140
|
+
|
|
141
|
+
# Run the request.
|
|
142
|
+
if persistent
|
|
143
|
+
@client.start unless @client.started?
|
|
144
|
+
response = request_runner.call
|
|
145
|
+
else
|
|
146
|
+
response = @client.start(&request_runner)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
response
|
|
150
|
+
### </snip> end shameless stealing from Marcel Molina
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Setup an HTTP client instance.
|
|
154
|
+
#
|
|
155
|
+
# Note that when you send your first request, the client is set
|
|
156
|
+
# up using whichever parameters for host and port you passed the first
|
|
157
|
+
# time. If you change the host or port, the client will be regenerated.
|
|
158
|
+
#
|
|
159
|
+
# +url+ is a URI instance generated from a full URL, including a host
|
|
160
|
+
# name and scheme.
|
|
161
|
+
def init_client(url)
|
|
162
|
+
host = url.host || HOST
|
|
163
|
+
port = url.port
|
|
164
|
+
if @client.nil? or @client.port != port or @client.address != host
|
|
165
|
+
@client = HTTP.new(host, port)
|
|
166
|
+
@client.use_ssl = false
|
|
167
|
+
|
|
168
|
+
# Check whether client needs to use SSL.
|
|
169
|
+
if port == PORT
|
|
170
|
+
# turn off SSL certificate verification
|
|
171
|
+
@client.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
172
|
+
@client.use_ssl = true
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Perform a get request.
|
|
178
|
+
def do_get(options={}, headers={})
|
|
179
|
+
do_request('GET', options, nil, headers)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Perform a put request.
|
|
183
|
+
def do_put(data, options={}, headers={})
|
|
184
|
+
do_request('PUT', options, data, headers)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Perform a delete request.
|
|
188
|
+
def do_delete(options={}, headers={})
|
|
189
|
+
do_request('DELETE', options, headers)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Perform a head request.
|
|
193
|
+
def do_head(options={}, headers={})
|
|
194
|
+
do_request('HEAD', options, headers)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
data/lib/s33r/s33r_exception.rb
CHANGED
|
@@ -1,25 +1,38 @@
|
|
|
1
1
|
module S33r
|
|
2
|
-
module
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
module S3Exception
|
|
3
|
+
|
|
4
|
+
# For errors originated by S3
|
|
5
|
+
class S3OriginatedException < Exception
|
|
6
|
+
attr_reader :s3_code, :s3_message
|
|
7
|
+
|
|
8
|
+
def initialize(code=nil, message=nil)
|
|
9
|
+
@s3_code = code
|
|
10
|
+
@s3_message = message
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_s
|
|
14
|
+
"S3 returned an error\nError code: #{@s3_code}; error message: #{@s3_message}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.error(s3_code, s3_message=nil)
|
|
19
|
+
S3OriginatedException.new(s3_code, s3_message)
|
|
5
20
|
end
|
|
6
21
|
|
|
22
|
+
# Errors originated by S33r.
|
|
23
|
+
class MethodNotAllowed < Exception
|
|
24
|
+
end
|
|
25
|
+
|
|
7
26
|
class MissingRequiredHeaders < Exception
|
|
8
27
|
end
|
|
9
28
|
|
|
10
29
|
class UnsupportedCannedACL < Exception
|
|
11
30
|
end
|
|
12
31
|
|
|
13
|
-
class UnsupportedHTTPMethod < Exception
|
|
14
|
-
end
|
|
15
|
-
|
|
16
32
|
class MalformedBucketName < Exception
|
|
17
33
|
end
|
|
18
34
|
|
|
19
|
-
class
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
class MissingResource < Exception
|
|
35
|
+
class InvalidBucket < Exception
|
|
23
36
|
end
|
|
24
37
|
|
|
25
38
|
class BucketListingMaxKeysError < Exception
|
|
@@ -28,23 +41,21 @@ module S33r
|
|
|
28
41
|
class InvalidBucketListing < Exception
|
|
29
42
|
end
|
|
30
43
|
|
|
31
|
-
class
|
|
44
|
+
class InvalidGroupType < Exception
|
|
32
45
|
end
|
|
33
46
|
|
|
34
|
-
class
|
|
47
|
+
class InvalidPermission < Exception
|
|
35
48
|
end
|
|
36
49
|
|
|
37
|
-
|
|
50
|
+
# Raised if an attempt is made to generate an authenticated URL
|
|
51
|
+
# with one of the required AWS keys missing.
|
|
52
|
+
class KeysIncomplete < Exception
|
|
38
53
|
end
|
|
39
54
|
|
|
40
55
|
# Raised if a bucket cannot be used as a log target
|
|
41
|
-
# (i.e. if LogDelivery permissions not set - see S33r::S3ACL::
|
|
56
|
+
# (i.e. if LogDelivery permissions not set - see S33r::S3ACL::Policy.add_log_target_grants)
|
|
42
57
|
class BucketNotLogTargetable < Exception
|
|
43
58
|
end
|
|
44
|
-
|
|
45
|
-
# Raised if you try to do a put with empty body
|
|
46
|
-
class TryingToPutEmptyResource < Exception
|
|
47
|
-
end
|
|
48
59
|
|
|
49
60
|
end
|
|
50
61
|
end
|
data/lib/s33r/s33r_http.rb
CHANGED
|
@@ -1,31 +1,48 @@
|
|
|
1
1
|
require 'net/http'
|
|
2
|
-
|
|
2
|
+
base = File.dirname(__FILE__)
|
|
3
|
+
require File.join(base, 's33r_exception')
|
|
4
|
+
require File.join(base, 'utility')
|
|
5
|
+
require File.join(base, 'libxml_loader')
|
|
6
|
+
require File.join(base, 'libxml_extensions')
|
|
3
7
|
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# Adds some convenience functions for checking response status
|
|
8
|
+
# Additions to the Net::HTTP classes
|
|
9
|
+
|
|
10
|
+
# Adds some convenience functions for checking response status, parsing
|
|
11
|
+
# error messages from
|
|
7
12
|
class Net::HTTPResponse
|
|
8
|
-
attr_accessor :success
|
|
9
13
|
attr_writer :body
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
# An exception wrapped around the response from S3
|
|
16
|
+
attr_reader :s3_error
|
|
17
|
+
|
|
18
|
+
# Wrap responses properly so the S3 error codes don't have to be read.
|
|
19
|
+
def conveniencify(method)
|
|
20
|
+
if '200' == code
|
|
21
|
+
@ok = true
|
|
22
|
+
@s3_message = 'Request successful'
|
|
23
|
+
# 204 returned for successful bucket or item deletes
|
|
24
|
+
elsif '204' == code and 'DELETE' == method
|
|
25
|
+
@s3_message = 'Successfully deleted'
|
|
26
|
+
@ok = true
|
|
27
|
+
else
|
|
28
|
+
@ok = false
|
|
29
|
+
if body.nil?
|
|
30
|
+
@s3_error = S33r::S3Exception.error(code)
|
|
31
|
+
else
|
|
32
|
+
# Get the S3 error message and code
|
|
33
|
+
error_response = XML.get_xml_doc(body)
|
|
34
|
+
s3_code = error_response.xget('//Code')
|
|
35
|
+
s3_message = error_response.xget('//Message')
|
|
36
|
+
|
|
37
|
+
@s3_error = S33r::S3Exception.error(s3_code, s3_message)
|
|
38
|
+
end
|
|
14
39
|
end
|
|
15
40
|
end
|
|
16
41
|
|
|
17
42
|
def ok?
|
|
18
|
-
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def success
|
|
22
|
-
code == '200'
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def not_found
|
|
26
|
-
code = '404'
|
|
43
|
+
@ok || false
|
|
27
44
|
end
|
|
28
|
-
|
|
45
|
+
|
|
29
46
|
def to_s
|
|
30
47
|
body
|
|
31
48
|
end
|
|
@@ -52,6 +69,7 @@ class Net::HTTPGenericRequest
|
|
|
52
69
|
self.each_capitalized do |key, value|
|
|
53
70
|
str += "#{key}: #{value}\n"
|
|
54
71
|
end
|
|
72
|
+
str += "*******\n" + body + "\n" unless body.nil?
|
|
55
73
|
str += "*******\n\n"
|
|
56
74
|
str
|
|
57
75
|
end
|
data/lib/s33r/s3_acl.rb
CHANGED
|
@@ -15,9 +15,9 @@ module S33r
|
|
|
15
15
|
#
|
|
16
16
|
# Represents both retrieved ACL XML or can be built up
|
|
17
17
|
# using objects and converted to XML.
|
|
18
|
-
# NB the
|
|
18
|
+
# NB the Policy is oblivious to the resource it is going
|
|
19
19
|
# to be applied to.
|
|
20
|
-
class
|
|
20
|
+
class Policy
|
|
21
21
|
# List of grants to be applied.
|
|
22
22
|
attr_accessor :grants, :owner
|
|
23
23
|
|
|
@@ -27,7 +27,7 @@ module S33r
|
|
|
27
27
|
@owner = owner
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
# Create an
|
|
30
|
+
# Create an Policy instance from a raw Access Control Policy XML document.
|
|
31
31
|
#
|
|
32
32
|
# +acl_xml+ is a raw Access Control Policy XML string (NOT libxml Document or Node).
|
|
33
33
|
#
|
|
@@ -50,7 +50,7 @@ module S33r
|
|
|
50
50
|
grants << Grant.new(grantee, permission)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Policy.new(owner, grants)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# Generate AccessControlPolicy XML document.
|
|
@@ -81,12 +81,10 @@ module S33r
|
|
|
81
81
|
# Returns true if grant was added;
|
|
82
82
|
# false otherwise (grant already exists).
|
|
83
83
|
def add_grant(grant)
|
|
84
|
-
|
|
85
|
-
return false
|
|
86
|
-
else
|
|
84
|
+
unless @grants.include?(grant)
|
|
87
85
|
@grants << grant
|
|
88
|
-
return true
|
|
89
86
|
end
|
|
87
|
+
self
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
# Remove a grant from the ACL document. Note that if you
|
|
@@ -100,6 +98,7 @@ module S33r
|
|
|
100
98
|
# false if it wasn't in the document.
|
|
101
99
|
def remove_grant(grant)
|
|
102
100
|
@grants.delete_if { |g| grant == g }
|
|
101
|
+
self
|
|
103
102
|
end
|
|
104
103
|
|
|
105
104
|
# Does the ACL contain a grant for public reads?
|
|
@@ -117,42 +116,15 @@ module S33r
|
|
|
117
116
|
add_grant(Grant.public_read_grant)
|
|
118
117
|
end
|
|
119
118
|
|
|
120
|
-
#
|
|
121
|
-
def
|
|
122
|
-
|
|
123
|
-
log_target_grants.each { |g| return false if !grants.include?(g) }
|
|
124
|
-
return true
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Add permissions to an instances which give READ_ACL
|
|
128
|
-
# and WRITE permissions to the LogDelivery group. Used
|
|
129
|
-
# to enable a bucket as a logging destination.
|
|
130
|
-
#
|
|
131
|
-
# Returns true if grants added, false otherwise
|
|
132
|
-
# (if already a log target).
|
|
133
|
-
def add_log_target_grants
|
|
134
|
-
if log_targetable?
|
|
135
|
-
return false
|
|
136
|
-
else
|
|
137
|
-
Grant.log_target_grants.each { |g| add_grant(g) }
|
|
138
|
-
return true
|
|
139
|
-
end
|
|
119
|
+
# Remove the public READ permission from this instance.
|
|
120
|
+
def remove_public_read_grant
|
|
121
|
+
remove_grant(Grant.public_read_grant)
|
|
140
122
|
end
|
|
141
123
|
|
|
142
|
-
#
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
# false otherwise.
|
|
146
|
-
#
|
|
147
|
-
# NB even if this method returns false, that doesn't mean
|
|
148
|
-
# the bucket is still a log target. Use log_targetable? to check
|
|
149
|
-
# whether a bucket can be used as a log target.
|
|
150
|
-
def remove_log_target_grants
|
|
151
|
-
ok = true
|
|
152
|
-
Grant.log_target_grants.each { |g| ok = ok and remove_grant(g) }
|
|
153
|
-
ok
|
|
124
|
+
# String representation of the policy.
|
|
125
|
+
def to_s
|
|
126
|
+
@grants.inject('') {|acc, grant| acc += "* " + grant.to_s + "\n"}
|
|
154
127
|
end
|
|
155
|
-
|
|
156
128
|
end
|
|
157
129
|
|
|
158
130
|
# Representation of an S3 Grant
|
|
@@ -171,7 +143,8 @@ module S33r
|
|
|
171
143
|
else
|
|
172
144
|
@permission = PERMISSIONS[permission]
|
|
173
145
|
end
|
|
174
|
-
raise InvalidPermission,
|
|
146
|
+
raise S3Exception::InvalidPermission, \
|
|
147
|
+
"Permission #{permission.to_s} is not a valid permission specifier" if @permission.nil?
|
|
175
148
|
end
|
|
176
149
|
|
|
177
150
|
# Note that setting a grant for an Amazon customer is the
|
|
@@ -196,15 +169,6 @@ module S33r
|
|
|
196
169
|
Grant.new(Group.new(:all_users), :read)
|
|
197
170
|
end
|
|
198
171
|
|
|
199
|
-
# Generator for a grant which gives the LogDelivery group
|
|
200
|
-
# write and read_acl permissions on a bucket.
|
|
201
|
-
#
|
|
202
|
-
# Returns an array with the two required Grant instances.
|
|
203
|
-
def Grant.log_target_grants
|
|
204
|
-
log_delivery_group = Group.new(:log_delivery)
|
|
205
|
-
[Grant.new(log_delivery_group, :read_acl), Grant.new(log_delivery_group, :write)]
|
|
206
|
-
end
|
|
207
|
-
|
|
208
172
|
# Convert a Grant object into an XML fragment.
|
|
209
173
|
def to_xml
|
|
210
174
|
xml_str = ""
|
|
@@ -239,6 +203,10 @@ module S33r
|
|
|
239
203
|
return true
|
|
240
204
|
end
|
|
241
205
|
|
|
206
|
+
def to_s
|
|
207
|
+
"#{@grantee.to_s} has permission #{@permission}"
|
|
208
|
+
end
|
|
209
|
+
|
|
242
210
|
end
|
|
243
211
|
|
|
244
212
|
# Abstract representation of an S3 Grantee.
|
|
@@ -291,6 +259,10 @@ module S33r
|
|
|
291
259
|
@grantee_type = GRANTEE_TYPES[:amazon_customer]
|
|
292
260
|
@email_address = email_address
|
|
293
261
|
end
|
|
262
|
+
|
|
263
|
+
def to_s
|
|
264
|
+
"Amazon customer with address '#{@email_address}"
|
|
265
|
+
end
|
|
294
266
|
end
|
|
295
267
|
|
|
296
268
|
# An S3 user.
|
|
@@ -315,6 +287,10 @@ module S33r
|
|
|
315
287
|
display_name = user_xml_doc.xget('DisplayName')
|
|
316
288
|
new(user_id, display_name)
|
|
317
289
|
end
|
|
290
|
+
|
|
291
|
+
def to_s
|
|
292
|
+
"Canonical user '#{@display_name}' (with user ID '#{@user_id}')"
|
|
293
|
+
end
|
|
318
294
|
end
|
|
319
295
|
|
|
320
296
|
# One of the predefined S3 groups.
|
|
@@ -327,11 +303,15 @@ module S33r
|
|
|
327
303
|
# one of the pre-defined Amazon group types.
|
|
328
304
|
def initialize(group_type)
|
|
329
305
|
unless S3_GROUP_TYPES.has_key?(group_type)
|
|
330
|
-
raise
|
|
306
|
+
raise S3Exception::InvalidGroupType, 'No such group type #{group_type}'
|
|
331
307
|
end
|
|
332
308
|
@group_type = S3_GROUP_TYPES[group_type]
|
|
333
309
|
@grantee_type = GRANTEE_TYPES[:group]
|
|
334
310
|
end
|
|
311
|
+
|
|
312
|
+
def to_s
|
|
313
|
+
"Group '#{@group_type}'"
|
|
314
|
+
end
|
|
335
315
|
end
|
|
336
316
|
|
|
337
317
|
end
|