sinatra-s3 0.98
Sign up to get free protection for your applications and to get access to all the features.
- data/README +23 -0
- data/Rakefile +51 -0
- data/bin/sinatra-s3 +30 -0
- data/db/migrate/001_create_bits.rb +28 -0
- data/db/migrate/002_create_users.rb +24 -0
- data/db/migrate/003_create_bits_users.rb +16 -0
- data/db/migrate/004_create_torrents.rb +22 -0
- data/db/migrate/005_create_torrent_peers.rb +26 -0
- data/examples/README +9 -0
- data/examples/wiki.rb +199 -0
- data/examples/wiki.ru +5 -0
- data/examples/wikicloth/MIT-LICENSE +20 -0
- data/examples/wikicloth/README +81 -0
- data/examples/wikicloth/Rakefile +23 -0
- data/examples/wikicloth/init.rb +1 -0
- data/examples/wikicloth/install.rb +0 -0
- data/examples/wikicloth/lib/core_ext.rb +43 -0
- data/examples/wikicloth/lib/wiki_buffer/html_element.rb +237 -0
- data/examples/wikicloth/lib/wiki_buffer/link.rb +70 -0
- data/examples/wikicloth/lib/wiki_buffer/table.rb +159 -0
- data/examples/wikicloth/lib/wiki_buffer/var.rb +77 -0
- data/examples/wikicloth/lib/wiki_buffer.rb +279 -0
- data/examples/wikicloth/lib/wiki_cloth.rb +61 -0
- data/examples/wikicloth/lib/wiki_link_handler.rb +138 -0
- data/examples/wikicloth/lib/wikicloth.rb +5 -0
- data/examples/wikicloth/run_tests.rb +48 -0
- data/examples/wikicloth/sample_documents/air_force_one.wiki +170 -0
- data/examples/wikicloth/sample_documents/cheatsheet.wiki +205 -0
- data/examples/wikicloth/sample_documents/default.css +34 -0
- data/examples/wikicloth/sample_documents/elements.wiki +7 -0
- data/examples/wikicloth/sample_documents/george_washington.wiki +526 -0
- data/examples/wikicloth/sample_documents/images.wiki +15 -0
- data/examples/wikicloth/sample_documents/lists.wiki +421 -0
- data/examples/wikicloth/sample_documents/pipe_trick.wiki +68 -0
- data/examples/wikicloth/sample_documents/random.wiki +55 -0
- data/examples/wikicloth/sample_documents/tv.wiki +312 -0
- data/examples/wikicloth/sample_documents/wiki.png +0 -0
- data/examples/wikicloth/sample_documents/wiki_tables.wiki +410 -0
- data/examples/wikicloth/tasks/wikicloth_tasks.rake +0 -0
- data/examples/wikicloth/test/test_helper.rb +3 -0
- data/examples/wikicloth/test/wiki_cloth_test.rb +8 -0
- data/examples/wikicloth/uninstall.rb +0 -0
- data/examples/wikicloth/wikicloth-0.1.3.gem +0 -0
- data/examples/wikicloth/wikicloth.gemspec +69 -0
- data/lib/sinatra-s3/admin.rb +626 -0
- data/lib/sinatra-s3/base.rb +526 -0
- data/lib/sinatra-s3/errors.rb +51 -0
- data/lib/sinatra-s3/ext.rb +20 -0
- data/lib/sinatra-s3/helpers/acp.rb +100 -0
- data/lib/sinatra-s3/helpers/admin.rb +41 -0
- data/lib/sinatra-s3/helpers/tracker.rb +42 -0
- data/lib/sinatra-s3/helpers/versioning.rb +27 -0
- data/lib/sinatra-s3/helpers.rb +79 -0
- data/lib/sinatra-s3/models/bit.rb +180 -0
- data/lib/sinatra-s3/models/bucket.rb +81 -0
- data/lib/sinatra-s3/models/file_info.rb +3 -0
- data/lib/sinatra-s3/models/git_bucket.rb +3 -0
- data/lib/sinatra-s3/models/slot.rb +47 -0
- data/lib/sinatra-s3/models/torrent.rb +6 -0
- data/lib/sinatra-s3/models/torrent_peer.rb +5 -0
- data/lib/sinatra-s3/models/user.rb +35 -0
- data/lib/sinatra-s3/s3.rb +57 -0
- data/lib/sinatra-s3/tasks.rb +62 -0
- data/lib/sinatra-s3/tracker.rb +134 -0
- data/lib/sinatra-s3.rb +1 -0
- data/public/css/control.css +225 -0
- data/public/css/wiki.css +47 -0
- data/public/images/external-link.gif +0 -0
- data/public/js/prototype.js +2539 -0
- data/public/js/upload_status.js +117 -0
- data/public/test.html +8 -0
- data/s3.yml.example +17 -0
- data/test/s3api_test.rb +121 -0
- data/test/test_helper.rb +25 -0
- metadata +156 -0
@@ -0,0 +1,626 @@
|
|
1
|
+
require 'aws/s3'
|
2
|
+
|
3
|
+
module S3
|
4
|
+
|
5
|
+
class Admin < Sinatra::Base
|
6
|
+
|
7
|
+
helpers do
|
8
|
+
include S3::Helpers
|
9
|
+
include S3::AdminHelpers
|
10
|
+
end
|
11
|
+
|
12
|
+
set :sessions, :on
|
13
|
+
enable :inline_templates
|
14
|
+
|
15
|
+
before do
|
16
|
+
ActiveRecord::Base.verify_active_connections!
|
17
|
+
end
|
18
|
+
|
19
|
+
get '/control/?' do
|
20
|
+
login_required
|
21
|
+
redirect '/control/buckets'
|
22
|
+
end
|
23
|
+
|
24
|
+
get %r{^/control/s/(.*)} do
|
25
|
+
open(File.join(PUBLIC_PATH, params[:captures].first))
|
26
|
+
end
|
27
|
+
|
28
|
+
get '/control/login' do
|
29
|
+
r :login, "Login"
|
30
|
+
end
|
31
|
+
|
32
|
+
post '/control/login' do
|
33
|
+
@user = User.find_by_login params[:login]
|
34
|
+
if @user
|
35
|
+
if @user.password == hmac_sha1( params[:password], @user.secret )
|
36
|
+
session[:user_id] = @user.id
|
37
|
+
redirect '/control/buckets'
|
38
|
+
else
|
39
|
+
@user.errors.add(:password, 'is incorrect')
|
40
|
+
end
|
41
|
+
else
|
42
|
+
@user = User.new
|
43
|
+
@user.errors.add(:login, 'not found')
|
44
|
+
end
|
45
|
+
login_view
|
46
|
+
end
|
47
|
+
|
48
|
+
get '/control/logout' do
|
49
|
+
session[:user_id] = nil
|
50
|
+
redirect '/control'
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/control/buckets/?' do
|
54
|
+
login_required
|
55
|
+
load_buckets
|
56
|
+
r :buckets, "Buckets"
|
57
|
+
end
|
58
|
+
|
59
|
+
post '/control/buckets/?' do
|
60
|
+
login_required
|
61
|
+
begin
|
62
|
+
Bucket.find_root(params['bucket']['name'])
|
63
|
+
load_buckets
|
64
|
+
@bucket.errors.add_to_base("A bucket named `#{@input['bucket']['name']}' already exists.")
|
65
|
+
rescue NoSuchBucket
|
66
|
+
bucket = Bucket.new(params['bucket'])
|
67
|
+
redirect '/control/buckets' if bucket.save()
|
68
|
+
load_buckets
|
69
|
+
@bucket.errors.add_to_base("Invalid bucket name.")
|
70
|
+
end
|
71
|
+
r :buckets, "Buckets"
|
72
|
+
end
|
73
|
+
|
74
|
+
get '/control/buckets/:bucket/?' do
|
75
|
+
login_required
|
76
|
+
@bucket = Bucket.find_root(params[:bucket])
|
77
|
+
only_can_read @bucket
|
78
|
+
@files = Slot.find :all, :conditions => ['deleted = 0 AND parent_id = ?', @bucket.id], :order => 'name'
|
79
|
+
r :files, "/#{@bucket.name}"
|
80
|
+
end
|
81
|
+
|
82
|
+
post '/control/buckets/:bucket/?' do
|
83
|
+
login_required
|
84
|
+
@bucket = Bucket.find_root(params[:bucket])
|
85
|
+
only_can_write @bucket
|
86
|
+
|
87
|
+
if params['upfile'].nil? || params['upfile'].instance_of?(String)
|
88
|
+
@files = Slot.find :all, :conditions => ['deleted = 0 AND parent_id = ?', @bucket.id], :order => 'name'
|
89
|
+
redirect "/control/buckets/#{params[:bucket]}"
|
90
|
+
end
|
91
|
+
|
92
|
+
tmpf = params['upfile'][:tempfile]
|
93
|
+
readlen, md5 = 0, MD5.new
|
94
|
+
while part = tmpf.read(BUFSIZE)
|
95
|
+
readlen += part.size
|
96
|
+
md5 << part
|
97
|
+
end
|
98
|
+
|
99
|
+
fileinfo = FileInfo.new
|
100
|
+
fileinfo.mime_type = params['upfile'][:type] || "binary/octet-stream"
|
101
|
+
fileinfo.size = readlen
|
102
|
+
fileinfo.md5 = md5.hexdigest
|
103
|
+
fileinfo.etag = '"' + md5.hexdigest + '"'
|
104
|
+
|
105
|
+
mdata = {}
|
106
|
+
if defined?(EXIFR) && fileinfo.mime_type =~ /jpg|jpeg/
|
107
|
+
photo_data = EXIFR::JPEG.new(tmpf.path).to_hash
|
108
|
+
photo_data.each_pair do |key,value|
|
109
|
+
tmp = key.to_s.gsub(/[^a-z0-9]+/i, '-').downcase.gsub(/-$/,'')
|
110
|
+
mdata[tmp] = value.to_s
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
params['fname'] = params['upfile'][:filename] if params['fname'].blank?
|
115
|
+
begin
|
116
|
+
slot = @bucket.find_slot(params['fname'])
|
117
|
+
if slot.versioning_enabled?
|
118
|
+
nslot = slot.clone()
|
119
|
+
slot.update_attributes(:deleted => true)
|
120
|
+
slot = nslot
|
121
|
+
end
|
122
|
+
fileinfo.path = slot.obj.path
|
123
|
+
file_path = File.join(STORAGE_PATH,fileinfo.path)
|
124
|
+
slot.update_attributes(:owner_id => @user.id, :meta => mdata, :obj => fileinfo, :size => fileinfo.size)
|
125
|
+
FileUtils.mv(tmpf.path, file_path,{ :force => true })
|
126
|
+
rescue NoSuchKey
|
127
|
+
fileinfo.path = File.join(params[:bucket], rand(10000).to_s(36) + '_' + File.basename(tmpf.path))
|
128
|
+
fileinfo.path.succ! while File.exists?(File.join(STORAGE_PATH, fileinfo.path))
|
129
|
+
file_path = File.join(STORAGE_PATH,fileinfo.path)
|
130
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
131
|
+
FileUtils.mv(tmpf.path, file_path)
|
132
|
+
slot = Slot.create(:name => params['fname'], :owner_id => @user.id, :meta => mdata, :obj => fileinfo, :size => fileinfo.size)
|
133
|
+
slot.grant(:access => params['facl'].to_i)
|
134
|
+
@bucket.add_child(slot)
|
135
|
+
end
|
136
|
+
|
137
|
+
if slot.versioning_enabled?
|
138
|
+
begin
|
139
|
+
slot.git_repository.add(File.basename(fileinfo.path))
|
140
|
+
slot.git_repository.commit("Added #{slot.name} to the Git repository.")
|
141
|
+
slot.git_update
|
142
|
+
slot.update_attributes(:version => slot.git_object.objectish)
|
143
|
+
rescue => err
|
144
|
+
puts "[#{Time.now}] GIT: #{err}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
redirect "/control/buckets/#{params[:bucket]}"
|
149
|
+
end
|
150
|
+
|
151
|
+
post '/control/buckets/:bucket/versioning/?' do
|
152
|
+
login_required
|
153
|
+
@bucket = Bucket.find_root(params[:bucket])
|
154
|
+
only_can_write @bucket
|
155
|
+
@bucket.git_init if defined?(Git)
|
156
|
+
redirect "/control/buckets/#{@bucket.name}"
|
157
|
+
end
|
158
|
+
|
159
|
+
get %r{^/control/changes/(.+?)/(.+)$} do
|
160
|
+
login_required
|
161
|
+
@bucket = Bucket.find_root params[:captures].first
|
162
|
+
@file = @bucket.find_slot(params[:captures].last)
|
163
|
+
only_owner_of @bucket
|
164
|
+
@versions = @bucket.git_repository.log.path(File.basename(@file.obj.path))
|
165
|
+
r :changes, "Commit Log", :popup
|
166
|
+
end
|
167
|
+
|
168
|
+
post '/control/delete/:bucket/?' do
|
169
|
+
login_required
|
170
|
+
@bucket = Bucket.find_root(params[:bucket])
|
171
|
+
only_owner_of @bucket
|
172
|
+
if Slot.count(:conditions => ['deleted = 0 AND parent_id = ?', @bucket.id]) > 0
|
173
|
+
# FIXME: error message, bucket is not empty
|
174
|
+
else
|
175
|
+
@bucket.remove_from_filesystem()
|
176
|
+
@bucket.destroy()
|
177
|
+
end
|
178
|
+
redirect "/control/buckets"
|
179
|
+
end
|
180
|
+
|
181
|
+
post %r{^/control/delete/(.+?)/(.+)$} do
|
182
|
+
login_required
|
183
|
+
@bucket = Bucket.find_root(params[:captures].first)
|
184
|
+
only_can_write @bucket
|
185
|
+
@slot = @bucket.find_slot(params[:captures].last)
|
186
|
+
|
187
|
+
if @slot.versioning_enabled?
|
188
|
+
@slot.git_repository.remove(File.basename(@slot.obj.path))
|
189
|
+
@slot.git_repository.commit("Removed #{@slot.name} from the Git repository.")
|
190
|
+
@slot.git_update
|
191
|
+
end
|
192
|
+
|
193
|
+
@slot.remove_from_filesystem()
|
194
|
+
@slot.destroy()
|
195
|
+
redirect "/control/buckets/#{params[:captures].first}"
|
196
|
+
end
|
197
|
+
|
198
|
+
get "/control/profile/?" do
|
199
|
+
login_required
|
200
|
+
@usero = @user
|
201
|
+
r :profile, "Your Profile"
|
202
|
+
end
|
203
|
+
|
204
|
+
post "/control/profile/?" do
|
205
|
+
login_required
|
206
|
+
@user.update_attributes(params['user'])
|
207
|
+
@usero = @user
|
208
|
+
r :profile, "Your Profile"
|
209
|
+
end
|
210
|
+
|
211
|
+
get "/control/users/?" do
|
212
|
+
login_required
|
213
|
+
only_superusers
|
214
|
+
@usero = User.new
|
215
|
+
@users = User.find :all, :conditions => ['deleted != 1'], :order => 'login'
|
216
|
+
r :users, "User List"
|
217
|
+
end
|
218
|
+
|
219
|
+
post "/control/users/?" do
|
220
|
+
login_required
|
221
|
+
only_superusers
|
222
|
+
@usero = User.new params['user'].merge(:activated_at => Time.now)
|
223
|
+
if @usero.valid?
|
224
|
+
@usero.save()
|
225
|
+
redirect "/control/users"
|
226
|
+
else
|
227
|
+
@users = User.find :all, :conditions => ['deleted != 1'], :order => 'login'
|
228
|
+
r :users, "User List"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
get "/control/users/:login/?" do
|
233
|
+
login_required
|
234
|
+
only_superusers
|
235
|
+
@usero = User.find_by_login params[:login]
|
236
|
+
r :profile, @usero.login
|
237
|
+
end
|
238
|
+
|
239
|
+
post "/control/users/:login/?" do
|
240
|
+
login_required
|
241
|
+
only_superusers
|
242
|
+
@usero = User.find_by_login params[:login]
|
243
|
+
|
244
|
+
# if were not changing passwords remove blank values
|
245
|
+
if params['user']['password'].blank? && params['user']['password_confirmation'].blank?
|
246
|
+
params['user'].delete('password')
|
247
|
+
params['user'].delete('password_confirmation')
|
248
|
+
end
|
249
|
+
|
250
|
+
if @usero.update_attributes(params['user'])
|
251
|
+
redirect "/control/users/#{@usero.login}"
|
252
|
+
else
|
253
|
+
r :profile, @usero.login
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
post "/control/users/delete/:login/?" do
|
258
|
+
login_required
|
259
|
+
only_superusers
|
260
|
+
@usero = User.find_by_login params[:login]
|
261
|
+
if @usero.id == @user.id
|
262
|
+
# FIXME: notify user they cannot delete themselves
|
263
|
+
else
|
264
|
+
@usero.destroy
|
265
|
+
end
|
266
|
+
redirect "/control/users"
|
267
|
+
end
|
268
|
+
|
269
|
+
get %r{^/control/acl/(.+?)/(.+)$} do
|
270
|
+
login_required
|
271
|
+
@bucket = Bucket.find_root(params[:captures].first)
|
272
|
+
only_can_write_acp @bucket
|
273
|
+
@slot = @bucket.find_slot(params[:captures].last)
|
274
|
+
only_can_write @slot
|
275
|
+
r :acl, "Modify File Access", :popup
|
276
|
+
end
|
277
|
+
|
278
|
+
post %r{^/control/acl/(.+?)/(.+)$} do
|
279
|
+
login_required
|
280
|
+
@bucket = Bucket.find_root(params[:captures].first)
|
281
|
+
@slot = @bucket.find_slot(params[:captures].last)
|
282
|
+
only_owner_of @slot
|
283
|
+
case params[:acl]['type']
|
284
|
+
when "email"
|
285
|
+
@user = User.find(:first, :conditions => [ 'key = ? OR email = ?', params[:acl]['user_id'], params[:acl]['user_id'] ])
|
286
|
+
update_user_access(@slot,@user,"#{Bit.acl_text.invert[params[:acl]['access']]}00".to_i(8)) if @user
|
287
|
+
when "http://acs.amazonaws.com/groups/global/AuthenticatedUsers"
|
288
|
+
@slot.access &= ~(@slot.access.to_s(8)[1,1].to_i*10)
|
289
|
+
@slot.access |= (Bit.acl_text.invert[params[:acl]['access']]*10).to_s.to_i(8)
|
290
|
+
when "http://acs.amazonaws.com/groups/global/AllUsers"
|
291
|
+
@slot.access &= ~@slot.access.to_s(8)[2,1].to_i
|
292
|
+
@slot.access |= Bit.acl_text.invert[params[:acl]['access']].to_s.to_i(8)
|
293
|
+
end
|
294
|
+
@slot.save()
|
295
|
+
redirect "/control/acl/#{@bucket.name}/#{@slot.name}"
|
296
|
+
end
|
297
|
+
|
298
|
+
get %r{^/control/meta/(.+?)/(.+)$} do
|
299
|
+
login_required
|
300
|
+
@bucket = Bucket.find_root(params[:captures].first)
|
301
|
+
@slot = @bucket.find_slot(params[:captures].last)
|
302
|
+
only_can_write @slot
|
303
|
+
r :meta, "Metadata", :popup
|
304
|
+
end
|
305
|
+
|
306
|
+
post %r{^/control/meta/(.+?)/(.+)$} do
|
307
|
+
login_required
|
308
|
+
@bucket = Bucket.find_root(params[:captures].first)
|
309
|
+
@slot = @bucket.find_slot(params[:captures].last)
|
310
|
+
only_can_write @slot
|
311
|
+
|
312
|
+
newm = {}
|
313
|
+
params[:m].each do |k,v|
|
314
|
+
newm[k] = v unless v.blank?
|
315
|
+
end
|
316
|
+
if !params[:meta]['key'].blank? && !params[:meta]['value'].blank?
|
317
|
+
if params[:meta]['key'] =~ /^[A-Za-z0-9\-]+$/
|
318
|
+
newm[params[:meta]['key']] = params[:meta]['value']
|
319
|
+
else
|
320
|
+
@slot.errors.add(:key, "can only contain letters, numbers and dashes")
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
@slot.update_attributes({ :meta => newm })
|
325
|
+
r :meta, "Metadata", :popup
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
331
|
+
|
332
|
+
__END__
|
333
|
+
|
334
|
+
@@ layout
|
335
|
+
%html
|
336
|
+
%head
|
337
|
+
%title Control Center » #{@title}
|
338
|
+
%script{ :language => "JavaScript", :type => "text/javascript", :src => "/control/s/js/prototype.js" }
|
339
|
+
%style{ :type => "text/css" }
|
340
|
+
@import '/control/s/css/control.css';
|
341
|
+
%body
|
342
|
+
%div#page
|
343
|
+
- if @user and not @login
|
344
|
+
%div.menu
|
345
|
+
%ul
|
346
|
+
%li
|
347
|
+
%a{ :href => "/control/buckets" } buckets
|
348
|
+
- if @user.superuser?
|
349
|
+
%a{ :href => "/control/users" } users
|
350
|
+
%a{ :href => "/control/profile" } profile
|
351
|
+
%a{ :href => "/control/logout" } logout
|
352
|
+
%div#header
|
353
|
+
%h1 Control Center
|
354
|
+
%h2 #{@title}
|
355
|
+
%div#content
|
356
|
+
= yield
|
357
|
+
|
358
|
+
@@ popup
|
359
|
+
%html
|
360
|
+
%head
|
361
|
+
%title #{@title}
|
362
|
+
%style{ :type => "text/css" }
|
363
|
+
@import '/control/s/css/control.css';
|
364
|
+
%script{ :language => 'javascript', :src => '/control/s/js/prototype.js' }
|
365
|
+
%body
|
366
|
+
%div#content
|
367
|
+
= yield
|
368
|
+
|
369
|
+
@@ login
|
370
|
+
%form.create{ :method => "post" }
|
371
|
+
%div.required
|
372
|
+
%label{ :for => "login" } User
|
373
|
+
%input#login{ :type => "text", :name => "login" }
|
374
|
+
%div.required
|
375
|
+
%label{ :for => "password" } Password
|
376
|
+
%input#password{ :type => "password", :name => "password" }
|
377
|
+
%input#loggo{ :type => "submit", :value => "Login", :name => "loggo" }
|
378
|
+
|
379
|
+
@@ buckets
|
380
|
+
- if @buckets.any?
|
381
|
+
%table
|
382
|
+
%thead
|
383
|
+
%tr
|
384
|
+
%th Name
|
385
|
+
%th Contains
|
386
|
+
%th Updated on
|
387
|
+
%th Info
|
388
|
+
%th Actions
|
389
|
+
%tbody
|
390
|
+
- @buckets.each do |bucket|
|
391
|
+
%tr
|
392
|
+
%th
|
393
|
+
%a{ :href => "/control/buckets/#{bucket.name}" } #{bucket.name}
|
394
|
+
%td #{bucket.total_children rescue 0} files
|
395
|
+
%td #{bucket.updated_at}
|
396
|
+
%td #{bucket.access_readable + (bucket.versioning_enabled? ? ",versioned" : "")}
|
397
|
+
%td
|
398
|
+
%a{ :href => "/control/delete/#{bucket.name}", :onClick => S3::POST, :title => "Delete Bucket #{bucket.name}" } Delete
|
399
|
+
- else
|
400
|
+
%p A sad day. You have no buckets yet.
|
401
|
+
%h3 Create a Bucket
|
402
|
+
%form.create{ :method => "post" }
|
403
|
+
= preserve errors_for(@bucket)
|
404
|
+
%input{ :name => "bucket[owner_id]", :type => "hidden", :value => @bucket.owner_id }
|
405
|
+
%div.required
|
406
|
+
%label{ :for => "bucket[name]" } Bucket Name
|
407
|
+
%input{ :name => "bucket[name]", :type => "text", :value => @bucket.name }
|
408
|
+
%div.required
|
409
|
+
%label{ :for => "bucket[access]" } Permissions
|
410
|
+
%select{ :name => "bucket[access]" }
|
411
|
+
- S3::CANNED_ACLS.sort.each do |acl,perm|
|
412
|
+
- opts = { :value => perm }
|
413
|
+
- opts[:selected] = true if perm == @bucket.access
|
414
|
+
%option{ opts } #{acl}
|
415
|
+
%input#newbucket{ :type => "submit", :value => "Create", :name => "newbucket" }
|
416
|
+
|
417
|
+
@@ files
|
418
|
+
%p Click on a file name to get file details.
|
419
|
+
%table
|
420
|
+
%caption
|
421
|
+
- if defined?(Git)
|
422
|
+
%span{ :style => "float:right" }
|
423
|
+
- if !@bucket.versioning_enabled?
|
424
|
+
%a{ :href => "/control/buckets/#{@bucket.name}/versioning", :onClick => S3::POST } Enable Versioning For This Bucket
|
425
|
+
- else
|
426
|
+
Versioning Enabled
|
427
|
+
%a{ :href => "/control/buckets" } ← Buckets
|
428
|
+
%thead
|
429
|
+
%tr
|
430
|
+
%th File
|
431
|
+
%th Size
|
432
|
+
%th Permission
|
433
|
+
%tbody
|
434
|
+
- if @files.empty?
|
435
|
+
%tr
|
436
|
+
%td{ :colspan => "3", :style => "padding:15px;text-align:center" } No Files
|
437
|
+
- @files.each do |file|
|
438
|
+
%tr
|
439
|
+
%td
|
440
|
+
%a{ :href => "javascript:///", :onclick => "$('details-#{file.id}').toggle()" } #{file.name}
|
441
|
+
%div.details{ :id => "details-#{file.id}", :style => "display:none" }
|
442
|
+
- if @bucket.versioning_enabled? && !file.git_object.nil?
|
443
|
+
%p Revision: #{file.git_object.objectish}
|
444
|
+
- if file.torrent
|
445
|
+
%p #{file.torrent.seeders} seeders • #{file.torrent.leechers} leechers • #{file.torrent.total} downloads
|
446
|
+
%p Last modified on #{file.updated_at}
|
447
|
+
%p
|
448
|
+
%a{ :href => signed_url("/#{@bucket.name}/#{file.name}"), :target => "_blank" } Get
|
449
|
+
•
|
450
|
+
%a{ :href => "/control/acl/#{@bucket.name}/#{file.name}", :onclick => S3::POPUP } Access
|
451
|
+
•
|
452
|
+
%a{ :href => "/control/meta/#{@bucket.name}/#{file.name}", :onclick => S3::POPUP } Meta
|
453
|
+
•
|
454
|
+
- if @bucket.versioning_enabled?
|
455
|
+
%a{ :href => "/control/changes/#{@bucket.name}/#{file.name}", :onclick => S3::POPUP } Changes
|
456
|
+
•
|
457
|
+
- if defined?(RubyTorrent)
|
458
|
+
%a{ :href => signed_url("/#{@bucket.name}/#{file.name}") + "&torrent", :target => "_blank" } Torrent
|
459
|
+
•
|
460
|
+
%a{ :href => "/control/delete/#{@bucket.name}/#{file.name}", :onclick => S3::POST, :title => "Delete file #{file.name}" } Delete
|
461
|
+
%td #{number_to_human_size(file.size)}
|
462
|
+
%td #{file.access_readable}
|
463
|
+
%div#results
|
464
|
+
%div#progress-bar{ :style => "display:none" }
|
465
|
+
%iframe#upload{ :name => "upload", :style => "display:none" }
|
466
|
+
- @upid = Time.now.to_f
|
467
|
+
- form_options = { :action => "?upload_id=#{@upid}", :id => "upload-form", :method => 'post', :enctype => 'multipart/form-data' }
|
468
|
+
- form_options.merge!({ :onsubmit => "UploadProgress.monitor('#{@upid}')", :target => "upload" }) if $UPLOAD_PROGRESS
|
469
|
+
%form.create{ form_options }
|
470
|
+
%h3 Upload a File
|
471
|
+
%div.required
|
472
|
+
%input{ :name => "upfile", :type => "file" }
|
473
|
+
%div.optional
|
474
|
+
%label{ :for => "fname"} File Name
|
475
|
+
%input{ :name => "fname", :type => "text" }
|
476
|
+
%div.required
|
477
|
+
%label{ :for => "facl" } Permissions
|
478
|
+
%select{ :name => "facl" }
|
479
|
+
- S3::CANNED_ACLS.sort.each do |acl, perm|
|
480
|
+
- opts = { :value => perm }
|
481
|
+
- opts[:selected] = true if perm == @bucket.access
|
482
|
+
%option{ opts } #{acl}
|
483
|
+
%input#newfile{ :name => "newfile", :value => "Create", :type => "submit" }
|
484
|
+
|
485
|
+
@@ users
|
486
|
+
%table
|
487
|
+
%thead
|
488
|
+
%tr
|
489
|
+
%th Login
|
490
|
+
%th Activated On
|
491
|
+
%th Total Storage
|
492
|
+
%th Actions
|
493
|
+
%tbody
|
494
|
+
- @users.each do |user|
|
495
|
+
%tr
|
496
|
+
%th
|
497
|
+
%a{ :href => "/control/users/#{user.login}" } #{user.login}
|
498
|
+
%td #{user.activated_at}
|
499
|
+
%td #{number_to_human_size(Bit.sum(:size, :conditions => [ 'owner_id = ?', user.id ]))}
|
500
|
+
%td
|
501
|
+
%a{ :href => "/control/users/delete/#{user.login}", :onclick => S3::POST, :title => "Delete user #{user.login}" } Delete
|
502
|
+
%h3 Create a User
|
503
|
+
%form.create{ :action => "/control/users", :method => "post" }
|
504
|
+
= preserve errors_for(@usero)
|
505
|
+
%div.required
|
506
|
+
%label{ :for => "user[login]" } Login
|
507
|
+
%input.large{ :type => "text", :value => @usero.login, :name => "user[login]" }
|
508
|
+
%div.required.inline
|
509
|
+
%label{ :for => "user[superuser]" } Is a super-admin?
|
510
|
+
%input{ :type => "checkbox", :name => "user[superuser]", :value => @usero.superuser }
|
511
|
+
%div.required
|
512
|
+
%label{ :for => "user[password]" } Password
|
513
|
+
%input.fixed{ :type => "password", :name => "user[email]" }
|
514
|
+
%div.required
|
515
|
+
%label{ :for => "user[password_confirmation]" } Password again
|
516
|
+
%input.fixed{ :type => "password", :name => "user[password_confirmation]" }
|
517
|
+
%div.required
|
518
|
+
%label{ :for => "user[email]" } Email
|
519
|
+
%input{ :type => "text", :value => @usero.email, :name => "user[email]" }
|
520
|
+
%div.required
|
521
|
+
%label{ :for => "user[key]" } Key (must be unique)
|
522
|
+
%input.fixed.long{ :type => "text", :value => (@usero.key || generate_key), :name => "user[key]" }
|
523
|
+
%div.required
|
524
|
+
%label{ :for => "user[secret]" } Secret
|
525
|
+
%input.fixed.long{ :type => "text", :value => (@usero.secret || generate_secret), :name => "user[secret]" }
|
526
|
+
%input.newuser{ :type => "submit", :value => "Create", :name => "newuser" }
|
527
|
+
|
528
|
+
@@ profile
|
529
|
+
%form.create{ :method => "post" }
|
530
|
+
= preserve errors_for(@usero)
|
531
|
+
- if @user.superuser?
|
532
|
+
%div.required.inline
|
533
|
+
%label{ :for => "user[superuser]" } Is a super-admin?
|
534
|
+
%input{ :type => "checkbox", :name => "user[superuser]", :value => @usero.superuser }
|
535
|
+
%div.required
|
536
|
+
%label{ :for => "user[password]" } Password
|
537
|
+
%input.fixed{ :type => "password", :name => "user[email]" }
|
538
|
+
%div.required
|
539
|
+
%label{ :for => "user[password_confirmation]" } Password again
|
540
|
+
%input.fixed{ :type => "password", :name => "user[password_confirmation]" }
|
541
|
+
%div.required
|
542
|
+
%label{ :for => "user[email]" } Email
|
543
|
+
%input{ :type => "text", :value => @usero.email, :name => "user[email]" }
|
544
|
+
%div.required
|
545
|
+
%label{ :for => "key" } Key
|
546
|
+
%h4 #{@usero.key}
|
547
|
+
%div.required
|
548
|
+
%label{ :for => "secret" } Secret
|
549
|
+
%h4 #{@usero.secret}
|
550
|
+
%input#saveuser{ :type => "submit", :value => "Save", :name => "saveuser" }
|
551
|
+
|
552
|
+
@@ meta
|
553
|
+
%form.create{ :method => "post", :style => "text-align:left" }
|
554
|
+
= preserve errors_for(@slot)
|
555
|
+
%table
|
556
|
+
%thead
|
557
|
+
%tr
|
558
|
+
%th Key
|
559
|
+
%th Value
|
560
|
+
%tbody
|
561
|
+
- if @slot.meta.empty?
|
562
|
+
%tr
|
563
|
+
%td{ :colspan => "2", :style => "padding:8px;text-align:center" } No Metadata for #{@slot.name}
|
564
|
+
- else
|
565
|
+
- @slot.meta.each do |k,v|
|
566
|
+
%tr
|
567
|
+
%td #{k}
|
568
|
+
%td
|
569
|
+
%input{ :name => "m[#{k}]", :type => "text", :value => v, :style => "width:100%" }
|
570
|
+
%thead
|
571
|
+
%tr
|
572
|
+
%th{ :colspan => "2" } New Key
|
573
|
+
%tbody
|
574
|
+
%tr
|
575
|
+
%td
|
576
|
+
%input{ :name => "meta[key]", :type => "text", :style => "width:100%" }
|
577
|
+
%td
|
578
|
+
%input{ :name => "meta[value]", :type => "text", :style => "width:100%" }
|
579
|
+
%div{ :style => "text-align:center;margin-top:15px" }
|
580
|
+
%input{ :type => "submit", :value => "Update" }
|
581
|
+
|
582
|
+
@@ changes
|
583
|
+
%table
|
584
|
+
%thead
|
585
|
+
%tr
|
586
|
+
%th Commit Log For #{@file.name}
|
587
|
+
%tbody
|
588
|
+
- @versions.each do |version|
|
589
|
+
%tr
|
590
|
+
%td
|
591
|
+
%div
|
592
|
+
%a{ :target => "_blank", :href => signed_url("/#{@bucket.name}/#{@file.name}") + "&version-id=#{version.sha}" } #{version.sha}
|
593
|
+
%div On: #{version.date}
|
594
|
+
%div By: #{version.author.name} <#{version.author.email}>
|
595
|
+
|
596
|
+
@@ acl
|
597
|
+
%table
|
598
|
+
%thead
|
599
|
+
%tr
|
600
|
+
%th For
|
601
|
+
%th Access
|
602
|
+
%tbody
|
603
|
+
- @slot.acl_list.each_pair do |key,acl|
|
604
|
+
%tr
|
605
|
+
%td #{acl[:type] == "CanonicalUser" ? "#{acl[:id]} (#{acl[:name]})" : acl[:uri].split("/").last}
|
606
|
+
%td #{acl[:access]}
|
607
|
+
%div{ :style => "text-align:left;margin-top:10px" }
|
608
|
+
%h3 Modify File Access
|
609
|
+
%form.create{ :method => "post" }
|
610
|
+
%div.required
|
611
|
+
%label{ :for => "acl_type" } For
|
612
|
+
%select#acl_type{ :name => "acl[type]", :onchange => "$('user_id_box').style.display = this.value == 'email' ? 'block' : 'none';" }
|
613
|
+
%option{ :value => "http://acs.amazonaws.com/groups/global/AllUsers" } AllUsers
|
614
|
+
%option{ :value => "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" } AuthenticatedUsers
|
615
|
+
%option{ :value => "email" } By ID/Email
|
616
|
+
%div#user_id_box.required{ :style => "display:none" }
|
617
|
+
%label{ :for => "user_id" } User ID/Email
|
618
|
+
%input#user_id{ :type => "text", :name => "acl[user_id]" }
|
619
|
+
%div.required
|
620
|
+
%label{ :for => "user_access" } Access
|
621
|
+
%select#user_access{ :name => "acl[access]" }
|
622
|
+
%option{ :value => "READ" } READ
|
623
|
+
%option{ :value => "READ_ACP" } READ_ACP
|
624
|
+
%option{ :value => "WRITE" } WRITE
|
625
|
+
%option{ :value => "WRITE_ACP" } WRITE_ACP
|
626
|
+
%input{ :type => "submit", :value => "Update" }
|