s33r 0.4.2 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|