diff --git a/charge.rb b/charge.rb
index 773ff08..8ad69ea 100644
--- a/charge.rb
+++ b/charge.rb
@@ -11,6 +11,7 @@
require 'lib/charge/factories/upload_spec_factory'
require 'lib/charge/factories/edit_spec_factory'
+require 'lib/charge/factories/delete_spec_factory'
SOURCE_BUCKET='ifixit-static-source'
LIVE_BUCKET='ifixit-assets'
@@ -100,6 +101,54 @@ def enforce_static_prefix path
'sorry, restoration not yet implemented'
end
+get '/bulk-upload/*' do
+ @directory = params[:splat].first
+ enforce_static_prefix @directory
+ @bulk = true
+ erb :upload
+end
+
+post '/bulk-upload-handler/*' do
+ halt 400, "you must choose files to upload!" if params[:files].nil? || params[:files].empty?
+ upload_specs = Charge::Factories::UploadSpecFactory::from_form_params_bulk params
+ upload_specs.each { |spec| enforce_static_prefix spec.key }
+ stream do |output|
+ bulk_uploader = Charge::Actions::BulkUploader.new upload_specs
+ bulk_uploader.set_output_stream output
+ bulk_uploader.upload
+ end
+end
+
+get '/delete/*' do
+ @key = params[:splat].first
+ enforce_static_prefix @key
+ @is_directory = false
+ @parent_directory = get_parent_dir @key
+ erb :delete_confirm
+end
+
+get '/delete-dir/*' do
+ @key = params[:splat].first
+ enforce_static_prefix @key
+ @is_directory = true
+ @parent_directory = get_parent_dir @key
+ s3service = Charge::Config.s3service.new()
+ @affected_keys = s3service.all_keys_under(LIVE_BUCKET, @key)
+ erb :delete_confirm
+end
+
+post '/delete-handler/*' do
+ key = params[:splat].first
+ enforce_static_prefix key
+ is_directory = params['is_directory'] == 'true'
+ delete_spec = Charge::Factories::DeleteSpecFactory::from_params(key, is_directory: is_directory)
+ stream do |output|
+ deleter = Charge::Actions::Deleter.new delete_spec
+ deleter.set_output_stream output
+ deleter.delete
+ end
+end
+
get '/worst' do
s3service = Charge::Config.s3service.new()
@biggest = s3service.find_largest_objects(LIVE_BUCKET, BASE_PREFIX, 100)
diff --git a/lib/charge/actions/bulk_uploader.rb b/lib/charge/actions/bulk_uploader.rb
new file mode 100644
index 0000000..5d89b7f
--- /dev/null
+++ b/lib/charge/actions/bulk_uploader.rb
@@ -0,0 +1,28 @@
+require 'charge'
+require 'actions/uploader'
+require 'helpers/streaming_output'
+
+module Charge
+ module Actions
+ class BulkUploader
+ include Helpers::StreamingOutput
+ def initialize upload_specs
+ @upload_specs = upload_specs
+ end
+
+ def upload
+ total = @upload_specs.length
+ stream_msg "Starting bulk upload of #{total} file(s)..."
+ @upload_specs.each_with_index do |spec, index|
+ stream_msg "
"
+ stream_msg "File #{index + 1} of #{total}: #{spec.filename}"
+ uploader = Actions::Uploader.new spec
+ uploader.set_output_stream @output_stream
+ uploader.upload
+ end
+ stream_msg "
"
+ stream_msg "Bulk upload complete! #{total} file(s) processed."
+ end
+ end
+ end
+end
diff --git a/lib/charge/actions/deleter.rb b/lib/charge/actions/deleter.rb
new file mode 100644
index 0000000..ee9ee7a
--- /dev/null
+++ b/lib/charge/actions/deleter.rb
@@ -0,0 +1,64 @@
+require 'charge'
+require 'helpers/streaming_output'
+require 'services/cache_buster'
+
+module Charge
+ module Actions
+ class Deleter
+ include Helpers::StreamingOutput
+ def initialize delete_spec
+ @delete_spec = delete_spec
+ @s3 = Config::s3service.new
+ end
+
+ def delete
+ if @delete_spec.is_directory
+ delete_directory
+ else
+ delete_single_file
+ end
+ provide_browse_link
+ end
+
+ private
+ def delete_single_file
+ key = @delete_spec.key
+ stream_msg "Deleting file '#{key}'..."
+ @s3.delete(Config.source_bucket, key)
+ stream_msg "Deleted from source bucket."
+ @s3.delete(Config.live_bucket, key)
+ stream_msg "Deleted from live bucket."
+ Services::CacheBuster.bust_cache_on_hosts key
+ stream_msg "Cache busted for '#{key}'."
+ end
+
+ def delete_directory
+ prefix = @delete_spec.key
+ stream_msg "Deleting all files under '#{prefix}'..."
+ keys = @s3.all_keys_under(Config.live_bucket, prefix)
+ count = 0
+ keys.each do |key|
+ count += 1
+ stream_msg "Deleting file #{count}: #{key}..."
+ @s3.delete(Config.source_bucket, key)
+ @s3.delete(Config.live_bucket, key)
+ Services::CacheBuster.bust_cache_on_hosts key
+ end
+ stream_msg "Deleted #{count} file(s)."
+ end
+
+ def provide_browse_link
+ key = @delete_spec.key
+ parent = parent_directory(key)
+ stream_msg %Q(Back to #{parent})
+ end
+
+ def parent_directory key
+ parts = key.chomp('/').split('/')
+ parts.pop
+ return Config.base_prefix if parts.empty?
+ parts.join('/') + '/'
+ end
+ end
+ end
+end
diff --git a/lib/charge/charge.rb b/lib/charge/charge.rb
index 771a1f6..7e90b30 100644
--- a/lib/charge/charge.rb
+++ b/lib/charge/charge.rb
@@ -4,6 +4,8 @@
require 'actions/uploader'
require 'actions/editor'
+require 'actions/deleter'
+require 'actions/bulk_uploader'
require 'exceptions'
diff --git a/lib/charge/factories/delete_spec_factory.rb b/lib/charge/factories/delete_spec_factory.rb
new file mode 100644
index 0000000..7ff6b36
--- /dev/null
+++ b/lib/charge/factories/delete_spec_factory.rb
@@ -0,0 +1,13 @@
+require 'values/delete_spec'
+
+module Charge
+ module Factories
+ class DeleteSpecFactory
+ class << self
+ def from_params key, is_directory:
+ Values::DeleteSpec.new(key, is_directory: is_directory)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/charge/factories/upload_spec_factory.rb b/lib/charge/factories/upload_spec_factory.rb
index 0b2c0ba..262ec93 100644
--- a/lib/charge/factories/upload_spec_factory.rb
+++ b/lib/charge/factories/upload_spec_factory.rb
@@ -25,6 +25,28 @@ def from_form_params params
return upload_spec
end
+ def from_form_params_bulk params
+ directory = params[:splat].first
+ directory = ensure_ends_in_slash(directory)
+ files = params[:files]
+ files.map do |file|
+ upload_spec = Values::UploadSpec.new(
+ directory,
+ file[:filename],
+ file)
+ if params["allow_overwrite"] == "on"
+ upload_spec.set_allow_overwrite
+ end
+ unless params["default_conversion"] == "on"
+ upload_spec.disable_conversion
+ end
+ if params["convert_to_jpeg"] == "on"
+ upload_spec.set_convert_to_jpeg
+ end
+ upload_spec
+ end
+ end
+
def ensure_ends_in_slash directory
directory_without_slashes = directory.sub(/\/+$/, '')
directory_ending_in_slash = directory_without_slashes + '/'
diff --git a/lib/charge/services/s3.rb b/lib/charge/services/s3.rb
index 2528724..e959864 100644
--- a/lib/charge/services/s3.rb
+++ b/lib/charge/services/s3.rb
@@ -67,6 +67,18 @@ def upload file, bucket, key
puts resp.to_h
end
+ def delete bucket, key
+ puts "Deleting #{key} from bucket #{bucket}..."
+ client.delete_object({
+ bucket: bucket,
+ key: key,
+ })
+ end
+
+ def all_keys_under bucket, prefix
+ find_whole_bucket(bucket, prefix).map { |item| item['key'] }
+ end
+
def exists_in_s3? bucket, key
s3 = Aws::S3::Resource.new(region: @region)
s3bucket = s3.bucket(bucket)
@@ -128,6 +140,9 @@ class S3Stubbed < S3
def upload file, bucket, key
puts "UPLOADS STUBBED FOR TESTING!"
end
+ def delete bucket, key
+ puts "DELETES STUBBED FOR TESTING!"
+ end
end
end
end
diff --git a/lib/charge/values/delete_spec.rb b/lib/charge/values/delete_spec.rb
new file mode 100644
index 0000000..d06d4e3
--- /dev/null
+++ b/lib/charge/values/delete_spec.rb
@@ -0,0 +1,13 @@
+module Charge
+ module Values
+ class DeleteSpec
+ attr :key
+ attr :is_directory
+
+ def initialize key, is_directory: false
+ @key = key
+ @is_directory = is_directory
+ end
+ end
+ end
+end
diff --git a/views/browse.erb b/views/browse.erb
index 46961fc..526a477 100644
--- a/views/browse.erb
+++ b/views/browse.erb
@@ -1,5 +1,5 @@
Browse
-
+
diff --git a/views/delete_confirm.erb b/views/delete_confirm.erb
new file mode 100644
index 0000000..7f9c1d0
--- /dev/null
+++ b/views/delete_confirm.erb
@@ -0,0 +1,23 @@
+Confirm Deletion
+
+<% if @is_directory %>
+ Delete directory: <%= @key %>
+ The following files will be permanently deleted:
+
+ <% @affected_keys.each do |key| %>
+ - <%= key %>
+ <% end %>
+
+<% else %>
+ Delete file: <%= @key %>
+ This file will be permanently deleted from both source and live buckets.
+<% end %>
+
+
+
+
+Cancel and go back
diff --git a/views/upload.erb b/views/upload.erb
index 8390b32..273a619 100644
--- a/views/upload.erb
+++ b/views/upload.erb
@@ -1,3 +1,23 @@
+<% if @bulk %>
+Bulk Upload Files
+
+
+<% else %>
Upload a file
+<% end %>
diff --git a/views/view.erb b/views/view.erb
index c7005f2..bb45f5c 100644
--- a/views/view.erb
+++ b/views/view.erb
@@ -8,6 +8,9 @@
Edit this image
+
+ Delete this image
+
Current Live Image: