aliyun-oss-ex 0.7.0.1402831795
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/COPYING +19 -0
- data/INSTALL +35 -0
- data/README +443 -0
- data/Rakefile +334 -0
- data/bin/oss +6 -0
- data/bin/setup.rb +11 -0
- data/lib/aliyun/oss.rb +55 -0
- data/lib/aliyun/oss/acl.rb +132 -0
- data/lib/aliyun/oss/authentication.rb +222 -0
- data/lib/aliyun/oss/base.rb +241 -0
- data/lib/aliyun/oss/bucket.rb +320 -0
- data/lib/aliyun/oss/connection.rb +279 -0
- data/lib/aliyun/oss/error.rb +70 -0
- data/lib/aliyun/oss/exceptions.rb +134 -0
- data/lib/aliyun/oss/extensions.rb +405 -0
- data/lib/aliyun/oss/logging.rb +304 -0
- data/lib/aliyun/oss/object.rb +612 -0
- data/lib/aliyun/oss/owner.rb +45 -0
- data/lib/aliyun/oss/parsing.rb +100 -0
- data/lib/aliyun/oss/response.rb +181 -0
- data/lib/aliyun/oss/service.rb +52 -0
- data/lib/aliyun/oss/version.rb +14 -0
- data/support/faster-xml-simple/lib/faster_xml_simple.rb +188 -0
- data/support/faster-xml-simple/test/regression_test.rb +48 -0
- data/support/faster-xml-simple/test/test_helper.rb +18 -0
- data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +47 -0
- data/support/rdoc/code_info.rb +212 -0
- data/test/acl_test.rb +70 -0
- data/test/authentication_test.rb +114 -0
- data/test/base_test.rb +137 -0
- data/test/bucket_test.rb +75 -0
- data/test/connection_test.rb +218 -0
- data/test/error_test.rb +71 -0
- data/test/extensions_test.rb +346 -0
- data/test/fixtures.rb +90 -0
- data/test/fixtures/buckets.yml +133 -0
- data/test/fixtures/errors.yml +34 -0
- data/test/fixtures/headers.yml +3 -0
- data/test/fixtures/logging.yml +15 -0
- data/test/fixtures/loglines.yml +5 -0
- data/test/fixtures/logs.yml +7 -0
- data/test/fixtures/policies.yml +16 -0
- data/test/logging_test.rb +90 -0
- data/test/mocks/fake_response.rb +27 -0
- data/test/object_test.rb +221 -0
- data/test/parsing_test.rb +67 -0
- data/test/remote/acl_test.rb +28 -0
- data/test/remote/bucket_test.rb +147 -0
- data/test/remote/logging_test.rb +86 -0
- data/test/remote/object_test.rb +350 -0
- data/test/remote/test_file.data +0 -0
- data/test/remote/test_helper.rb +34 -0
- data/test/response_test.rb +69 -0
- data/test/service_test.rb +24 -0
- data/test/test_helper.rb +110 -0
- metadata +177 -0
data/Rakefile
ADDED
@@ -0,0 +1,334 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rdoc/task'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rubygems/package_task'
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + '/lib/aliyun/oss'
|
9
|
+
|
10
|
+
def library_root
|
11
|
+
File.dirname(__FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => :test
|
15
|
+
|
16
|
+
Rake::TestTask.new do |test|
|
17
|
+
test.pattern = 'test/*_test.rb'
|
18
|
+
test.verbose = true
|
19
|
+
end
|
20
|
+
|
21
|
+
namespace :doc do
|
22
|
+
Rake::RDocTask.new do |rdoc|
|
23
|
+
rdoc.rdoc_dir = 'doc'
|
24
|
+
rdoc.title = "Aliyun::OSS -- Support for Aliyun OSS's REST api"
|
25
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
26
|
+
rdoc.rdoc_files.include('README')
|
27
|
+
rdoc.rdoc_files.include('COPYING')
|
28
|
+
rdoc.rdoc_files.include('INSTALL')
|
29
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
30
|
+
end
|
31
|
+
|
32
|
+
task :rdoc => 'doc:readme'
|
33
|
+
|
34
|
+
task :refresh => :rerdoc do
|
35
|
+
system 'open doc/index.html'
|
36
|
+
end
|
37
|
+
|
38
|
+
task :readme do
|
39
|
+
require File.dirname(__FILE__) + '/support/rdoc/code_info'
|
40
|
+
RDoc::CodeInfo.parse('lib/**/*.rb')
|
41
|
+
|
42
|
+
strip_comments = lambda {|comment| comment.gsub(/^# ?/, '')}
|
43
|
+
docs_for = lambda do |location|
|
44
|
+
info = RDoc::CodeInfo.for(location)
|
45
|
+
raise RuntimeError, "Couldn't find documentation for `#{location}'" unless info
|
46
|
+
strip_comments[info.comment]
|
47
|
+
end
|
48
|
+
|
49
|
+
open('README', 'w') do |file|
|
50
|
+
file.write ERB.new(IO.read('README.erb')).result(binding)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
task :deploy => :rerdoc do
|
55
|
+
sh %(scp -r doc marcel@rubyforge.org:/var/www/gforge-projects/aliyun/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
namespace :dist do
|
60
|
+
spec = Gem::Specification.new do |s|
|
61
|
+
s.name = 'aliyun-oss-ex'
|
62
|
+
s.version = Gem::Version.new(Aliyun::OSS::Version)
|
63
|
+
s.summary = "Client library for Aliyun's Open Storage Service's REST API"
|
64
|
+
s.description = s.summary
|
65
|
+
s.email = 'fanzc.daily@gmail.com'
|
66
|
+
s.author = 'steve'
|
67
|
+
s.has_rdoc = true
|
68
|
+
s.extra_rdoc_files = %w(README COPYING INSTALL)
|
69
|
+
s.homepage = 'https://github.com/fanzc/aliyun-oss-sdk-for-ruby'
|
70
|
+
s.files = FileList['Rakefile', 'lib/**/*.rb', 'bin/*', 'support/**/*.rb']
|
71
|
+
s.executables << 'oss'
|
72
|
+
s.test_files = Dir['test/**/*']
|
73
|
+
|
74
|
+
s.add_dependency 'xml-simple'
|
75
|
+
s.add_dependency 'builder'
|
76
|
+
s.add_dependency 'mime-types'
|
77
|
+
s.rdoc_options = ['--title', "Aliyun::OSS -- Support for Aliyun OSS's REST api",
|
78
|
+
'--main', 'README',
|
79
|
+
'--line-numbers', '--inline-source']
|
80
|
+
end
|
81
|
+
|
82
|
+
# Regenerate README before packaging
|
83
|
+
#task :package => 'doc:readme' #TODO 暂时不生成文档
|
84
|
+
task :package
|
85
|
+
Gem::PackageTask.new(spec) do |pkg|
|
86
|
+
pkg.need_tar_gz = true
|
87
|
+
pkg.package_files.include('{lib,script,test,support}/**/*')
|
88
|
+
pkg.package_files.include('README')
|
89
|
+
pkg.package_files.include('COPYING')
|
90
|
+
pkg.package_files.include('INSTALL')
|
91
|
+
pkg.package_files.include('Rakefile')
|
92
|
+
end
|
93
|
+
|
94
|
+
desc 'Install with gems'
|
95
|
+
task :install => :repackage do
|
96
|
+
sh "gem i pkg/#{spec.name}-#{spec.version}.gem"
|
97
|
+
end
|
98
|
+
|
99
|
+
desc 'Uninstall gem'
|
100
|
+
task :uninstall do
|
101
|
+
sh "gem uninstall #{spec.name} -x"
|
102
|
+
end
|
103
|
+
|
104
|
+
desc 'Reinstall gem'
|
105
|
+
task :reinstall => [:uninstall, :install]
|
106
|
+
|
107
|
+
task :confirm_release do
|
108
|
+
print "Releasing version #{spec.version}. Are you sure you want to proceed? [Yn] "
|
109
|
+
abort if STDIN.getc == ?n
|
110
|
+
end
|
111
|
+
|
112
|
+
desc 'Tag release'
|
113
|
+
task :tag do
|
114
|
+
sh %(git tag -a '#{spec.version}-release' -m 'Tagging #{spec.version} release')
|
115
|
+
sh 'git push --tags'
|
116
|
+
end
|
117
|
+
|
118
|
+
desc 'Update changelog to include a release marker'
|
119
|
+
task :add_release_marker_to_changelog do
|
120
|
+
changelog = IO.read('CHANGELOG')
|
121
|
+
changelog.sub!(/^head:/, "#{spec.version}:")
|
122
|
+
|
123
|
+
open('CHANGELOG', 'w') do |file|
|
124
|
+
file.write "head:\n\n#{changelog}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
task :commit_changelog do
|
129
|
+
sh %(git commit CHANGELOG -m "Bump changelog version marker for release")
|
130
|
+
sh 'git push'
|
131
|
+
end
|
132
|
+
|
133
|
+
package_name = lambda {|specification| File.join('pkg', "#{specification.name}-#{specification.version}")}
|
134
|
+
|
135
|
+
desc 'Push a release to rubyforge'
|
136
|
+
task :release => [:confirm_release, :clean, :add_release_marker_to_changelog, :package, :commit_changelog, :tag] do
|
137
|
+
require 'rubyforge'
|
138
|
+
package = package_name[spec]
|
139
|
+
|
140
|
+
rubyforge = RubyForge.new.configure
|
141
|
+
rubyforge.login
|
142
|
+
|
143
|
+
user_config = rubyforge.userconfig
|
144
|
+
user_config['release_changes'] = YAML.load_file('CHANGELOG')[spec.version.to_s].join("\n")
|
145
|
+
|
146
|
+
version_already_released = lambda do
|
147
|
+
releases = rubyforge.autoconfig['release_ids']
|
148
|
+
releases.has_key?(spec.name) && releases[spec.name][spec.version.to_s]
|
149
|
+
end
|
150
|
+
|
151
|
+
abort("Release #{spec.version} already exists!") if version_already_released.call
|
152
|
+
|
153
|
+
begin
|
154
|
+
rubyforge.add_release(spec.rubyforge_project, spec.name, spec.version.to_s, "#{package}.tar.gz", "#{package}.gem")
|
155
|
+
puts "Version #{spec.version} released!"
|
156
|
+
rescue Exception => exception
|
157
|
+
puts 'Release failed!'
|
158
|
+
raise
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
desc 'Upload a beta gem'
|
163
|
+
task :push_beta_gem => [:clobber_package, :package] do
|
164
|
+
beta_gem = package_name[spec]
|
165
|
+
#sh %(scp #{beta_gem}.gem marcel@rubyforge.org:/var/www/gforge-projects/aliyun/beta)
|
166
|
+
sh %(gem push #{beta_gem}.gem)
|
167
|
+
end
|
168
|
+
|
169
|
+
task :spec do
|
170
|
+
puts spec.to_ruby
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
desc 'Check code to test ratio'
|
175
|
+
task :stats do
|
176
|
+
library_files = FileList["#{library_root}/lib/**/*.rb"]
|
177
|
+
test_files = FileList["#{library_root}/test/**/*_test.rb"]
|
178
|
+
count_code_lines = Proc.new do |lines|
|
179
|
+
lines.inject(0) do |code_lines, line|
|
180
|
+
next code_lines if [/^\s*$/, /^\s*#/].any? {|non_code_line| non_code_line === line}
|
181
|
+
code_lines + 1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
count_code_lines_for_files = Proc.new do |files|
|
186
|
+
files.inject(0) {|code_lines, file| code_lines + count_code_lines[IO.read(file)]}
|
187
|
+
end
|
188
|
+
|
189
|
+
library_code_lines = count_code_lines_for_files[library_files]
|
190
|
+
test_code_lines = count_code_lines_for_files[test_files]
|
191
|
+
ratio = Proc.new { sprintf('%.2f', test_code_lines.to_f / library_code_lines)}
|
192
|
+
|
193
|
+
puts "Code LOC: #{library_code_lines} Test LOC: #{test_code_lines} Code to Test Ratio: 1:#{ratio.call}"
|
194
|
+
end
|
195
|
+
|
196
|
+
namespace :test do
|
197
|
+
find_file = lambda do |name|
|
198
|
+
file_name = lambda {|path| File.join(path, "#{name}.rb")}
|
199
|
+
root = $:.detect do |path|
|
200
|
+
File.exist?(file_name[path])
|
201
|
+
end
|
202
|
+
file_name[root] if root
|
203
|
+
end
|
204
|
+
|
205
|
+
TEST_LOADER = find_file['rake/rake_test_loader']
|
206
|
+
multiruby = lambda do |glob|
|
207
|
+
system 'multiruby', TEST_LOADER, *Dir.glob(glob)
|
208
|
+
end
|
209
|
+
|
210
|
+
desc 'Check test coverage'
|
211
|
+
task :coverage do
|
212
|
+
system("rcov -x Library -x support --sort coverage #{File.join(library_root, 'test/*_test.rb')}")
|
213
|
+
show_test_coverage_results
|
214
|
+
end
|
215
|
+
|
216
|
+
Rake::TestTask.new(:remote) do |test|
|
217
|
+
test.pattern = 'test/remote/*_test.rb'
|
218
|
+
test.verbose = true
|
219
|
+
end
|
220
|
+
|
221
|
+
Rake::TestTask.new(:all) do |test|
|
222
|
+
test.pattern = 'test/**/*_test.rb'
|
223
|
+
test.verbose = true
|
224
|
+
end
|
225
|
+
|
226
|
+
desc 'Check test coverage of full stack remote tests'
|
227
|
+
task :full_coverage do
|
228
|
+
system("rcov -x Library -x support --sort coverage #{File.join(library_root, 'test/remote/*_test.rb')} #{File.join(library_root, 'test/*_test.rb')}")
|
229
|
+
show_test_coverage_results
|
230
|
+
end
|
231
|
+
|
232
|
+
desc 'Run local tests against multiple versions of Ruby'
|
233
|
+
task :version_audit do
|
234
|
+
multiruby['test/*_test.rb']
|
235
|
+
end
|
236
|
+
|
237
|
+
namespace :version_audit do
|
238
|
+
desc 'Run remote tests against multiple versions of Ruby'
|
239
|
+
task :remote do
|
240
|
+
multiruby['test/remote/*_test.rb']
|
241
|
+
end
|
242
|
+
|
243
|
+
desc 'Run all tests against multiple versions of Ruby'
|
244
|
+
task :all do
|
245
|
+
multiruby['test/**/*_test.rb']
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def show_test_coverage_results
|
250
|
+
system("open #{File.join(library_root, 'coverage/index.html')}") if PLATFORM['darwin']
|
251
|
+
end
|
252
|
+
|
253
|
+
desc 'Remove coverage products'
|
254
|
+
task :clobber_coverage do
|
255
|
+
rm_r 'coverage' rescue nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
namespace :todo do
|
260
|
+
class << TODOS = IO.read(File.join(library_root, 'TODO'))
|
261
|
+
def items
|
262
|
+
split("\n").grep(/^\[\s|X\]/)
|
263
|
+
end
|
264
|
+
|
265
|
+
def completed
|
266
|
+
find_items_matching(/^\[X\]/)
|
267
|
+
end
|
268
|
+
|
269
|
+
def uncompleted
|
270
|
+
find_items_matching(/^\[\s\]/)
|
271
|
+
end
|
272
|
+
|
273
|
+
def find_items_matching(regexp)
|
274
|
+
items.grep(regexp).instance_eval do
|
275
|
+
def display
|
276
|
+
puts map {|item| "* #{item.sub(/^\[[^\]]\]\s/, '')}"}
|
277
|
+
end
|
278
|
+
self
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
desc 'Completed todo items'
|
284
|
+
task :completed do
|
285
|
+
TODOS.completed.display
|
286
|
+
end
|
287
|
+
|
288
|
+
desc 'Incomplete todo items'
|
289
|
+
task :uncompleted do
|
290
|
+
TODOS.uncompleted.display
|
291
|
+
end
|
292
|
+
end if File.exists?(File.join(library_root, 'TODO'))
|
293
|
+
|
294
|
+
namespace :site do
|
295
|
+
require 'erb'
|
296
|
+
require 'rdoc'
|
297
|
+
|
298
|
+
readme = lambda { IO.read('README')[/^== Getting started\n(.*)/m, 1] }
|
299
|
+
|
300
|
+
readme_to_html = lambda do
|
301
|
+
handler = SM::ToHtml.new
|
302
|
+
handler.instance_eval do
|
303
|
+
require 'syntax'
|
304
|
+
require 'syntax/convertors/html'
|
305
|
+
def accept_verbatim(am, fragment)
|
306
|
+
syntax = Syntax::Convertors::HTML.for_syntax('ruby')
|
307
|
+
@res << %(<div class="ruby">#{syntax.convert(fragment.txt, true)}</div>)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
SM::SimpleMarkup.new.convert(readme.call, handler)
|
311
|
+
end
|
312
|
+
|
313
|
+
desc 'Regenerate the public website page'
|
314
|
+
task :build => 'doc:readme' do
|
315
|
+
open('site/public/index.html', 'w') do |file|
|
316
|
+
erb_data = {}
|
317
|
+
erb_data[:readme] = readme_to_html.call
|
318
|
+
file.write ERB.new(IO.read('site/index.erb')).result(binding)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
task :refresh => :build do
|
323
|
+
system 'open site/public/index.html'
|
324
|
+
end
|
325
|
+
|
326
|
+
desc 'Update the live website'
|
327
|
+
task :deploy => :build do
|
328
|
+
site_files = FileList['site/public/*']
|
329
|
+
site_files.delete_if {|file| File.directory?(file)}
|
330
|
+
sh %(scp #{site_files.join ' '} marcel@rubyforge.org:/var/www/gforge-projects/aliyun/)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
task :clean => ['dist:clobber_package', 'doc:clobber_rdoc', 'test:clobber_coverage']
|
data/bin/oss
ADDED
data/bin/setup.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
#!/usr/bin/env ruby
|
3
|
+
if ENV['OSS_ACCESS_KEY_ID'] && ENV['OSS_SECRET_ACCESS_KEY']
|
4
|
+
Aliyun::OSS::Base.establish_connection!(
|
5
|
+
:access_key_id => ENV['OSS_ACCESS_KEY_ID'],
|
6
|
+
:secret_access_key => ENV['OSS_SECRET_ACCESS_KEY']
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
require File.dirname(__FILE__) + '/../test/fixtures'
|
11
|
+
include Aliyun::OSS
|
data/lib/aliyun/oss.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'cgi'
|
3
|
+
require 'uri'
|
4
|
+
require 'openssl'
|
5
|
+
require 'digest/sha1'
|
6
|
+
require 'net/https'
|
7
|
+
require 'time'
|
8
|
+
require 'date'
|
9
|
+
require 'open-uri'
|
10
|
+
|
11
|
+
$:.unshift(File.dirname(__FILE__))
|
12
|
+
require 'oss/extensions'
|
13
|
+
require_library_or_gem 'builder' unless defined? Builder
|
14
|
+
require_library_or_gem 'mime/types', 'mime-types' unless defined? MIME::Types
|
15
|
+
|
16
|
+
require 'oss/base'
|
17
|
+
require 'oss/version'
|
18
|
+
require 'oss/parsing'
|
19
|
+
require 'oss/acl'
|
20
|
+
require 'oss/logging'
|
21
|
+
require 'oss/service'
|
22
|
+
require 'oss/owner'
|
23
|
+
require 'oss/bucket'
|
24
|
+
require 'oss/object'
|
25
|
+
require 'oss/error'
|
26
|
+
require 'oss/exceptions'
|
27
|
+
require 'oss/connection'
|
28
|
+
require 'oss/authentication'
|
29
|
+
require 'oss/response'
|
30
|
+
|
31
|
+
Aliyun::OSS::Base.class_eval do
|
32
|
+
include Aliyun::OSS::Connection::Management
|
33
|
+
end
|
34
|
+
|
35
|
+
Aliyun::OSS::Bucket.class_eval do
|
36
|
+
include Aliyun::OSS::Logging::Management
|
37
|
+
include Aliyun::OSS::ACL::Bucket
|
38
|
+
end
|
39
|
+
|
40
|
+
require_library_or_gem 'xmlsimple', 'xml-simple' unless defined? XmlSimple
|
41
|
+
# If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
|
42
|
+
# except it uses the xml/libxml library for xml parsing (rather than REXML). If libxml isn't installed, we just fall back on
|
43
|
+
# XmlSimple.
|
44
|
+
Aliyun::OSS::Parsing.parser =
|
45
|
+
begin
|
46
|
+
require_library_or_gem 'xml/libxml'
|
47
|
+
# Older version of libxml aren't stable (bus error when requesting attributes that don't exist) so we
|
48
|
+
# have to use a version greater than '0.3.8.2'.
|
49
|
+
raise LoadError unless XML::Parser::VERSION > '0.3.8.2'
|
50
|
+
$:.push(File.join(File.dirname(__FILE__), '..', '..', 'support', 'faster-xml-simple', 'lib'))
|
51
|
+
require_library_or_gem 'faster_xml_simple'
|
52
|
+
FasterXmlSimple
|
53
|
+
rescue LoadError
|
54
|
+
XmlSimple
|
55
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Aliyun
|
3
|
+
module OSS
|
4
|
+
# By default buckets are private. This means that only the owner has access rights to the bucket and its objects.
|
5
|
+
# Objects in that bucket inherit the permission of the bucket unless otherwise specified. When an object is private, the owner can
|
6
|
+
# generate a signed url that exposes the object to anyone who has that url. Alternatively, buckets and objects can be given other
|
7
|
+
# access levels. Several canned access levels are defined:
|
8
|
+
#
|
9
|
+
# * <tt>:private</tt> - Owner gets FULL_CONTROL. No one else has any access rights. This is the default.
|
10
|
+
# * <tt>:public_read</tt> - Owner gets FULL_CONTROL and the anonymous principal is granted READ access. If this policy is used on an object, it can be read from a browser with no authentication.
|
11
|
+
# * <tt>:public_read_write</tt> - Owner gets FULL_CONTROL, the anonymous principal is granted READ and WRITE access. This is a useful policy to apply to a bucket, if you intend for any anonymous user to PUT objects into the bucket.
|
12
|
+
#
|
13
|
+
# You can set a canned access level when you create a bucket or an object by using the <tt>:access</tt> option:
|
14
|
+
#
|
15
|
+
# OSSObject.store(
|
16
|
+
# 'kiss.jpg',
|
17
|
+
# data,
|
18
|
+
# 'marcel',
|
19
|
+
# :access => :public_read
|
20
|
+
# )
|
21
|
+
#
|
22
|
+
# Since the image we created is publicly readable, we can access it directly from a browser by going to the corresponding bucket name
|
23
|
+
# and specifying the object's key without a special authenticated url:
|
24
|
+
#
|
25
|
+
# http://oss.aliyuncs.com/marcel/kiss.jpg
|
26
|
+
#
|
27
|
+
module ACL
|
28
|
+
# The ACL::Policy class lets you inspect and modify access controls for buckets and objects.
|
29
|
+
# A policy is made up of one or more Grants which specify a permission and a Grantee to whom that permission is granted.
|
30
|
+
#
|
31
|
+
# Buckets and objects are given a default access policy which contains one grant permitting the owner of the bucket or object
|
32
|
+
# FULL_CONTROL over its contents. This means they can read the object, write to the object, as well as read and write its
|
33
|
+
# policy.
|
34
|
+
#
|
35
|
+
# The <tt>acl</tt> method for both buckets and objects returns the policy object for that entity:
|
36
|
+
#
|
37
|
+
# grant = Bucket.acl('some-bucket')
|
38
|
+
# grant = Bucket.acl('some-bucket', :public_read)
|
39
|
+
#
|
40
|
+
|
41
|
+
module Bucket
|
42
|
+
def self.included(klass) #:nodoc:
|
43
|
+
klass.extend(ClassMethods)
|
44
|
+
end
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
# The acl method is the single point of entry for reading and writing access control list policies for a given bucket.
|
48
|
+
#
|
49
|
+
# # Fetch the acl for the 'marcel' bucket
|
50
|
+
# policy = Bucket.acl 'marcel'
|
51
|
+
#
|
52
|
+
# # Modify the policy ...
|
53
|
+
# # Bucket.acl 'marcel', :public_read
|
54
|
+
def acl(name = nil, access_level = nil)
|
55
|
+
path = path(name) << '?acl'
|
56
|
+
if access_level
|
57
|
+
put(path, {:access => access_level})
|
58
|
+
acl(name)
|
59
|
+
else
|
60
|
+
respond_with(Policy::Response) do
|
61
|
+
policy = get(path).policy
|
62
|
+
policy.has_key?('access_control_list') && policy['access_control_list']['grant'][0]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# The acl method returns and updates the acl for a given bucket.
|
69
|
+
#
|
70
|
+
# # Fetch a bucket
|
71
|
+
# bucket = Bucket.find 'marcel'
|
72
|
+
#
|
73
|
+
# # view
|
74
|
+
# bucket.acl
|
75
|
+
#
|
76
|
+
# # write
|
77
|
+
# bucket.acl(:public_read)
|
78
|
+
def acl(reload = false)
|
79
|
+
expirable_memoize(reload) do
|
80
|
+
self.class.acl(name, reload)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class OptionProcessor #:nodoc:
|
86
|
+
attr_reader :options
|
87
|
+
class << self
|
88
|
+
def process!(options)
|
89
|
+
new(options).process!
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def initialize(options)
|
94
|
+
options.to_normalized_options!
|
95
|
+
@options = options
|
96
|
+
@access_level = extract_access_level
|
97
|
+
end
|
98
|
+
|
99
|
+
def process!
|
100
|
+
return unless access_level_specified?
|
101
|
+
validate!
|
102
|
+
options['x-oss-acl'] = access_level
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
def extract_access_level
|
107
|
+
options.delete('access') || options.delete('x-oss-acl')
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate!
|
111
|
+
raise InvalidAccessControlLevel.new(valid_levels, access_level) unless valid?
|
112
|
+
end
|
113
|
+
|
114
|
+
def valid?
|
115
|
+
valid_levels.include?(access_level)
|
116
|
+
end
|
117
|
+
|
118
|
+
def access_level_specified?
|
119
|
+
!@access_level.nil?
|
120
|
+
end
|
121
|
+
|
122
|
+
def valid_levels
|
123
|
+
%w(private public-read public-read-write)
|
124
|
+
end
|
125
|
+
|
126
|
+
def access_level
|
127
|
+
@normalized_access_level ||= @access_level.to_header
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|