gotime_aws 2.5.6

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/lib/s3/grantee.rb ADDED
@@ -0,0 +1,238 @@
1
+ module Aws
2
+
3
+ # There are 2 ways to set permissions for a bucket or key (called a +thing+ below):
4
+ #
5
+ # 1 . Use +perms+ param to set 'Canned Access Policies' when calling the <tt>bucket.create</tt>,
6
+ # <tt>bucket.put</tt> and <tt>key.put</tt> methods.
7
+ # The +perms+ param can take these values: 'private', 'public-read', 'public-read-write' and
8
+ # 'authenticated-read'.
9
+ # (see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html).
10
+ #
11
+ # bucket = s3.bucket('bucket_for_kd_test_13', true, 'public-read')
12
+ # key.put('Woohoo!','public-read-write' )
13
+ #
14
+ # 2 . Use Grantee instances (the permission is a +String+ or an +Array+ of: 'READ', 'WRITE',
15
+ # 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'):
16
+ #
17
+ # bucket = s3.bucket('my_awesome_bucket', true)
18
+ # grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c', FULL_CONTROL, :apply)
19
+ # grantee2 = Aws::S3::Grantee.new(bucket, 'xy3v3...5fhp', [READ, WRITE], :apply)
20
+ #
21
+ # There is only one way to get and to remove permission (via Grantee instances):
22
+ #
23
+ # grantees = bucket.grantees # a list of Grantees that have any access for this bucket
24
+ # grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c')
25
+ # grantee1.perms #=> returns a list of perms for this grantee to that bucket
26
+ # ...
27
+ # grantee1.drop # remove all perms for this grantee
28
+ # grantee2.revoke('WRITE') # revoke write access only
29
+ #
30
+ class S3::Grantee
31
+ # A bucket or a key the grantee has an access to.
32
+ attr_reader :thing
33
+ # Grantee Amazon id.
34
+ attr_reader :id
35
+ # Grantee display name.
36
+ attr_reader :name
37
+ # Array of permissions.
38
+ attr_accessor :perms
39
+
40
+ # Retrieve Owner information and a list of Grantee instances that have
41
+ # a access to this thing (bucket or key).
42
+ #
43
+ # bucket = s3.bucket('my_awesome_bucket', true, 'public-read')
44
+ # ...
45
+ # Aws::S3::Grantee.owner_and_grantees(bucket) #=> [owner, grantees]
46
+ #
47
+ def self.owner_and_grantees(thing)
48
+ if thing.is_a?(S3::Bucket)
49
+ bucket, key = thing, ''
50
+ else
51
+ bucket, key = thing.bucket, thing
52
+ end
53
+ hash = bucket.s3.interface.get_acl_parse(bucket.to_s, key.to_s)
54
+ owner = S3::Owner.new(hash[:owner][:id], hash[:owner][:display_name])
55
+
56
+ grantees = []
57
+ hash[:grantees].each do |id, params|
58
+ grantees << new(thing, id, params[:permissions], nil, params[:display_name])
59
+ end
60
+ [owner, grantees]
61
+ end
62
+
63
+ # Retrieves a list of Grantees instances that have an access to this thing(bucket or key).
64
+ #
65
+ # bucket = s3.bucket('my_awesome_bucket', true, 'public-read')
66
+ # ...
67
+ # Aws::S3::Grantee.grantees(bucket) #=> grantees
68
+ #
69
+ def self.grantees(thing)
70
+ owner_and_grantees(thing)[1]
71
+ end
72
+
73
+ def self.put_acl(thing, owner, grantees) #:nodoc:
74
+ if thing.is_a?(S3::Bucket)
75
+ bucket, key = thing, ''
76
+ else
77
+ bucket, key = thing.bucket, thing
78
+ end
79
+ body = "<AccessControlPolicy>" +
80
+ "<Owner>" +
81
+ "<ID>#{owner.id}</ID>" +
82
+ "<DisplayName>#{owner.name}</DisplayName>" +
83
+ "</Owner>" +
84
+ "<AccessControlList>" +
85
+ grantees.map { |grantee| grantee.to_xml }.join +
86
+ "</AccessControlList>" +
87
+ "</AccessControlPolicy>"
88
+ bucket.s3.interface.put_acl(bucket.to_s, key.to_s, body)
89
+ end
90
+
91
+ # Create a new Grantee instance.
92
+ # Grantee +id+ must exist on S3. If +action+ == :refresh, then retrieve
93
+ # permissions from S3 and update @perms. If +action+ == :apply, then apply
94
+ # perms to +thing+ at S3. If +action+ == :apply_and_refresh then it performs.
95
+ # both the actions. This is used for the new grantees that had no perms to
96
+ # this thing before. The default action is :refresh.
97
+ #
98
+ # bucket = s3.bucket('my_awesome_bucket', true, 'public-read')
99
+ # grantee1 = Aws::S3::Grantee.new(bucket, 'a123b...223c', FULL_CONTROL)
100
+ # ...
101
+ # grantee2 = Aws::S3::Grantee.new(bucket, 'abcde...asdf', [FULL_CONTROL, READ], :apply)
102
+ # grantee3 = Aws::S3::Grantee.new(bucket, 'aaaaa...aaaa', 'READ', :apply_and_refresh)
103
+ #
104
+ def initialize(thing, id, perms=[], action=:refresh, name=nil)
105
+ @thing = thing
106
+ @id = id
107
+ @name = name
108
+ @perms = perms.to_a
109
+ case action
110
+ when :apply then
111
+ apply
112
+ when :refresh then
113
+ refresh
114
+ when :apply_and_refresh then
115
+ apply; refresh
116
+ end
117
+ end
118
+
119
+ # Return +true+ if the grantee has any permissions to the thing.
120
+ def exists?
121
+ self.class.grantees(@thing).each do |grantee|
122
+ return true if @id == grantee.id
123
+ end
124
+ false
125
+ end
126
+
127
+ # Return Grantee type (+String+): "Group" or "CanonicalUser".
128
+ def type
129
+ @id[/^http:/] ? "Group" : "CanonicalUser"
130
+ end
131
+
132
+ # Return a name or an id.
133
+ def to_s
134
+ @name || @id
135
+ end
136
+
137
+ # Add permissions for grantee.
138
+ # Permissions: 'READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'.
139
+ # See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingPermissions.html .
140
+ # Returns +true+.
141
+ #
142
+ # grantee.grant('FULL_CONTROL') #=> true
143
+ # grantee.grant('FULL_CONTROL','WRITE','READ') #=> true
144
+ # grantee.grant(['WRITE_ACP','READ','READ_ACP']) #=> true
145
+ #
146
+ def grant(*permissions)
147
+ permissions.flatten!
148
+ old_perms = @perms.dup
149
+ @perms += permissions
150
+ @perms.uniq!
151
+ return true if @perms == old_perms
152
+ apply
153
+ end
154
+
155
+ # Revoke permissions for grantee.
156
+ # Permissions: 'READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'
157
+ # See http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingPermissions.html .
158
+ # Default value is 'FULL_CONTROL'.
159
+ # Returns +true+.
160
+ #
161
+ # grantee.revoke('READ') #=> true
162
+ # grantee.revoke('FULL_CONTROL','WRITE') #=> true
163
+ # grantee.revoke(['READ_ACP','WRITE_ACP']) #=> true
164
+ #
165
+ def revoke(*permissions)
166
+ permissions.flatten!
167
+ old_perms = @perms.dup
168
+ @perms -= permissions
169
+ @perms.uniq!
170
+ return true if @perms == old_perms
171
+ apply
172
+ end
173
+
174
+ # Revoke all permissions for this grantee.
175
+ # Returns +true+.
176
+ #
177
+ # grantee.drop #=> true
178
+ #
179
+ def drop
180
+ @perms = []
181
+ apply
182
+ end
183
+
184
+ # Refresh grantee perms for its +thing+.
185
+ # Returns +true+ if the grantee has perms for this +thing+ or
186
+ # +false+ otherwise, and updates @perms value as a side-effect.
187
+ #
188
+ # grantee.grant('FULL_CONTROL') #=> true
189
+ # grantee.refresh #=> true
190
+ # grantee.drop #=> true
191
+ # grantee.refresh #=> false
192
+ #
193
+ def refresh
194
+ @perms = []
195
+ self.class.grantees(@thing).each do |grantee|
196
+ if @id == grantee.id
197
+ @name = grantee.name
198
+ @perms = grantee.perms
199
+ return true
200
+ end
201
+ end
202
+ false
203
+ end
204
+
205
+ # Apply current grantee @perms to +thing+. This method is called internally by the +grant+
206
+ # and +revoke+ methods. In normal use this method should not
207
+ # be called directly.
208
+ #
209
+ # grantee.perms = ['FULL_CONTROL']
210
+ # grantee.apply #=> true
211
+ #
212
+ def apply
213
+ @perms.uniq!
214
+ owner, grantees = self.class.owner_and_grantees(@thing)
215
+ # walk through all the grantees and replace the data for the current one and ...
216
+ grantees.map! { |grantee| grantee.id == @id ? self : grantee }
217
+ # ... if this grantee is not known - add this bad boy to a list
218
+ grantees << self unless grantees.include?(self)
219
+ # set permissions
220
+ self.class.put_acl(@thing, owner, grantees)
221
+ end
222
+
223
+ def to_xml # :nodoc:
224
+ id_str = @id[/^http/] ? "<URI>#{@id}</URI>" : "<ID>#{@id}</ID>"
225
+ grants = ''
226
+ @perms.each do |perm|
227
+ grants << "<Grant>" +
228
+ "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
229
+ "xsi:type=\"#{type}\">#{id_str}</Grantee>" +
230
+ "<Permission>#{perm}</Permission>" +
231
+ "</Grant>"
232
+ end
233
+ grants
234
+ end
235
+
236
+ end
237
+
238
+ end
data/lib/s3/key.rb ADDED
@@ -0,0 +1,281 @@
1
+ module Aws
2
+
3
+
4
+ class S3::Key
5
+
6
+ attr_reader :bucket, :name, :last_modified, :e_tag, :size, :storage_class, :owner
7
+ attr_accessor :headers, :meta_headers
8
+ attr_writer :data
9
+
10
+ # Separate Amazon meta headers from other headers
11
+ def self.split_meta(headers) #:nodoc:
12
+ hash = headers.dup
13
+ meta = {}
14
+ hash.each do |key, value|
15
+ if key[/^#{S3Interface::AMAZON_METADATA_PREFIX}/]
16
+ meta[key.gsub(S3Interface::AMAZON_METADATA_PREFIX, '')] = value
17
+ hash.delete(key)
18
+ end
19
+ end
20
+ [hash, meta]
21
+ end
22
+
23
+ def self.add_meta_prefix(meta_headers, prefix=S3Interface::AMAZON_METADATA_PREFIX)
24
+ meta = {}
25
+ meta_headers.each do |meta_header, value|
26
+ if meta_header[/#{prefix}/]
27
+ meta[meta_header] = value
28
+ else
29
+ meta["#{S3Interface::AMAZON_METADATA_PREFIX}#{meta_header}"] = value
30
+ end
31
+ end
32
+ meta
33
+ end
34
+
35
+
36
+ # Create a new Key instance, but do not create the actual key.
37
+ # The +name+ is a +String+.
38
+ # Returns a new Key instance.
39
+ #
40
+ # key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
41
+ # key.exists? #=> true | false
42
+ # key.put('Woohoo!') #=> true
43
+ # key.exists? #=> true
44
+ #
45
+ def self.create(bucket, name, data=nil, meta_headers={})
46
+ new(bucket, name, data, {}, meta_headers)
47
+ end
48
+
49
+ # Create a new Key instance, but do not create the actual key.
50
+ # In normal use this method should not be called directly.
51
+ # Use Aws::S3::Key.create or bucket.key() instead.
52
+ #
53
+ def initialize(bucket, name, data=nil, headers={}, meta_headers={},
54
+ last_modified=nil, e_tag=nil, size=nil, storage_class=nil, owner=nil)
55
+ raise 'Bucket must be a Bucket instance.' unless bucket.is_a?(S3::Bucket)
56
+ @bucket = bucket
57
+ @name = name
58
+ @data = data
59
+ @e_tag = e_tag
60
+ @size = size.to_i
61
+ @storage_class = storage_class
62
+ @owner = owner
63
+ @last_modified = last_modified
64
+ if @last_modified && !@last_modified.is_a?(Time)
65
+ @last_modified = Time.parse(@last_modified)
66
+ end
67
+ @headers, @meta_headers = self.class.split_meta(headers)
68
+ @meta_headers.merge!(meta_headers)
69
+ end
70
+
71
+ # Return key name as a String.
72
+ #
73
+ # key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
74
+ # puts key #=> 'logs/today/1.log'
75
+ #
76
+ def to_s
77
+ @name.to_s
78
+ end
79
+
80
+ # Return the full S3 path to this key (bucket/key).
81
+ #
82
+ # key.full_name #=> 'my_awesome_bucket/cool_key'
83
+ #
84
+ def full_name(separator='/')
85
+ "#{@bucket.to_s}#{separator}#{@name}"
86
+ end
87
+
88
+ # Return a public link to a key.
89
+ #
90
+ # key.public_link #=> 'https://s3.amazonaws.com:443/my_awesome_bucket/cool_key'
91
+ #
92
+ def public_link
93
+ params = @bucket.s3.interface.params
94
+ "#{params[:protocol]}://#{params[:server]}:#{params[:port]}/#{full_name('/')}"
95
+ end
96
+
97
+ # Return Key data. Retrieve this data from Amazon if it is the first time call.
98
+ # TODO TRB 6/19/07 What does the above mean? Clarify.
99
+ #
100
+ def data
101
+ get if !@data and exists?
102
+ @data
103
+ end
104
+
105
+ # Retrieve object data and attributes from Amazon.
106
+ # Returns a +String+.
107
+ #
108
+ def get(headers={}, &block)
109
+ response = @bucket.s3.interface.get(@bucket.name, @name, headers, &block)
110
+ @data = response[:object]
111
+ @headers, @meta_headers = self.class.split_meta(response[:headers])
112
+ # refresh(false) Holy moly, this was doing two extra hits to s3 for making 3 hits for every get!!
113
+ @data
114
+ end
115
+
116
+ # Store object data on S3.
117
+ # Parameter +data+ is a +String+ or S3Object instance.
118
+ # Returns +true+.
119
+ #
120
+ # key = Aws::S3::Key.create(bucket, 'logs/today/1.log')
121
+ # key.data = 'Qwerty'
122
+ # key.put #=> true
123
+ # ...
124
+ # key.put('Olala!') #=> true
125
+ #
126
+ def put(data=nil, perms=nil, headers={})
127
+ headers['x-amz-acl'] = perms if perms
128
+ @data = data || @data
129
+ meta = self.class.add_meta_prefix(@meta_headers)
130
+ @bucket.s3.interface.put(@bucket.name, @name, @data, meta.merge(headers))
131
+ end
132
+
133
+ # Rename an object. Returns new object name.
134
+ #
135
+ # key = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
136
+ # key.rename('logs/today/2.log') #=> 'logs/today/2.log'
137
+ # puts key.name #=> 'logs/today/2.log'
138
+ # key.exists? #=> true
139
+ #
140
+ def rename(new_name)
141
+ @bucket.s3.interface.rename(@bucket.name, @name, new_name)
142
+ @name = new_name
143
+ end
144
+
145
+ # Create an object copy. Returns a destination Aws::S3::Key instance.
146
+ #
147
+ # # Key instance as destination
148
+ # key1 = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
149
+ # key2 = Aws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
150
+ # key1.put('Olala!') #=> true
151
+ # key1.copy(key2) #=> #<Aws::S3::Key:0xb7b5e240 ... >
152
+ # key1.exists? #=> true
153
+ # key2.exists? #=> true
154
+ # puts key2.data #=> 'Olala!'
155
+ #
156
+ # # String as destination
157
+ # key = Aws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
158
+ # key.put('Olala!') #=> true
159
+ # new_key = key.copy('logs/today/888.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
160
+ # key.exists? #=> true
161
+ # new_key.exists? #=> true
162
+ #
163
+ def copy(new_key_or_name)
164
+ new_key_or_name = S3::Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(S3::Key)
165
+ @bucket.s3.interface.copy(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
166
+ new_key_or_name
167
+ end
168
+
169
+ # Move an object to other location. Returns a destination Aws::S3::Key instance.
170
+ #
171
+ # # Key instance as destination
172
+ # key1 = Aws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
173
+ # key2 = Aws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
174
+ # key1.put('Olala!') #=> true
175
+ # key1.move(key2) #=> #<Aws::S3::Key:0xb7b5e240 ... >
176
+ # key1.exists? #=> false
177
+ # key2.exists? #=> true
178
+ # puts key2.data #=> 'Olala!'
179
+ #
180
+ # # String as destination
181
+ # key = Aws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<Aws::S3::Key:0xb7b1e240 ... >
182
+ # key.put('Olala!') #=> true
183
+ # new_key = key.move('logs/today/888.log') #=> #<Aws::S3::Key:0xb7b5e240 ... >
184
+ # key.exists? #=> false
185
+ # new_key.exists? #=> true
186
+ #
187
+ def move(new_key_or_name)
188
+ new_key_or_name = S3::Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(S3::Key)
189
+ @bucket.s3.interface.move(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
190
+ new_key_or_name
191
+ end
192
+
193
+ # Retrieve key info from bucket and update attributes.
194
+ # Refresh meta-headers (by calling +head+ method) if +head+ is set.
195
+ # Returns +true+ if the key exists in bucket and +false+ otherwise.
196
+ #
197
+ # key = Aws::S3::Key.create(bucket, 'logs/today/1.log')
198
+ # key.e_tag #=> nil
199
+ # key.meta_headers #=> {}
200
+ # key.refresh #=> true
201
+ # key.e_tag #=> '12345678901234567890bf11094484b6'
202
+ # key.meta_headers #=> {"family"=>"qwerty", "name"=>"asdfg"}
203
+ #
204
+ def refresh(head=true)
205
+ new_key = @bucket.key(self)
206
+ @last_modified = new_key.last_modified
207
+ @e_tag = new_key.e_tag
208
+ @size = new_key.size
209
+ @storage_class = new_key.storage_class
210
+ @owner = new_key.owner
211
+ if @last_modified
212
+ self.head
213
+ true
214
+ else
215
+ @headers = @meta_headers = {}
216
+ false
217
+ end
218
+ end
219
+
220
+ # Updates headers and meta-headers from S3.
221
+ # Returns +true+.
222
+ #
223
+ # key.meta_headers #=> {"family"=>"qwerty"}
224
+ # key.head #=> true
225
+ # key.meta_headers #=> {"family"=>"qwerty", "name"=>"asdfg"}
226
+ #
227
+ def head
228
+ @headers, @meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name))
229
+ true
230
+ end
231
+
232
+ # Reload meta-headers only. Returns meta-headers hash.
233
+ #
234
+ # key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
235
+ #
236
+ def reload_meta
237
+ @meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name)).last
238
+ end
239
+
240
+ # Replace meta-headers by new hash at S3. Returns new meta-headers hash.
241
+ #
242
+ # key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
243
+ # key.save_meta #=> {"family"=>"oops", "race" => "troll"}
244
+ # key.reload_meta #=> {"family"=>"oops", "race" => "troll"}
245
+ #
246
+ def save_meta(meta_headers)
247
+ meta = self.class.add_meta_prefix(meta_headers)
248
+ @bucket.s3.interface.copy(@bucket.name, @name, @bucket.name, @name, :replace, meta)
249
+ @meta_headers = self.class.split_meta(meta)[1]
250
+ end
251
+
252
+ # Check for existence of the key in the given bucket.
253
+ # Returns +true+ or +false+.
254
+ #
255
+ # key = Aws::S3::Key.create(bucket,'logs/today/1.log')
256
+ # key.exists? #=> false
257
+ # key.put('Woohoo!') #=> true
258
+ # key.exists? #=> true
259
+ #
260
+ def exists?
261
+ @bucket.key(self).last_modified ? true : false
262
+ end
263
+
264
+ # Remove key from bucket.
265
+ # Returns +true+.
266
+ #
267
+ # key.delete #=> true
268
+ #
269
+ def delete
270
+ raise 'Key name must be specified.' if Aws::Utils.blank?(@name)
271
+ @bucket.s3.interface.delete(@bucket, @name)
272
+ end
273
+
274
+ # Return a list of grantees.
275
+ #
276
+ def grantees
277
+ S3::Grantee::grantees(self)
278
+ end
279
+
280
+ end
281
+ end