Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions charge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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)
Expand Down
28 changes: 28 additions & 0 deletions lib/charge/actions/bulk_uploader.rb
Original file line number Diff line number Diff line change
@@ -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 "<hr>"
stream_msg "<b>File #{index + 1} of #{total}: #{spec.filename}</b>"
uploader = Actions::Uploader.new spec
uploader.set_output_stream @output_stream
uploader.upload
end
stream_msg "<hr>"
stream_msg "Bulk upload complete! #{total} file(s) processed."
end
end
end
end
64 changes: 64 additions & 0 deletions lib/charge/actions/deleter.rb
Original file line number Diff line number Diff line change
@@ -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 <a href="/browse/#{parent}">#{parent}</a>)
end

def parent_directory key
parts = key.chomp('/').split('/')
parts.pop
return Config.base_prefix if parts.empty?
parts.join('/') + '/'
end
end
end
end
2 changes: 2 additions & 0 deletions lib/charge/charge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

require 'actions/uploader'
require 'actions/editor'
require 'actions/deleter'
require 'actions/bulk_uploader'

require 'exceptions'

Expand Down
13 changes: 13 additions & 0 deletions lib/charge/factories/delete_spec_factory.rb
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions lib/charge/factories/upload_spec_factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 + '/'
Expand Down
15 changes: 15 additions & 0 deletions lib/charge/services/s3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
13 changes: 13 additions & 0 deletions lib/charge/values/delete_spec.rb
Original file line number Diff line number Diff line change
@@ -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
6 changes: 4 additions & 2 deletions views/browse.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h2>Browse</h2>
<h3><%= @directory %> + <a href="/upload/<%= @directory %>">Upload a new file here</a></h3>
<h3><%= @directory %> + <a href="/upload/<%= @directory %>">Upload a new file here</a> | <a href="/bulk-upload/<%= @directory %>">Bulk upload</a></h3>

<ul>
<li>📁 -
Expand All @@ -19,14 +19,16 @@
<a href="/browse/<%= @item.prefix %>">
<%= @item.prefix %>
</a>
<a href="/delete-dir/<%= @item.prefix %>" style="color: red; margin-left: 10px;">✕ delete</a>
</li>
<% end %>
<br>
<% for @item in @items['contents'] %>
<li><%= @item['size'] / 1024 %>K -
<a href="/view/<%= @item['key'] %>">
<%= @item['key'] %></li>
<%= @item['key'] %>
</a>
<a href="/delete/<%= @item['key'] %>" style="color: red; margin-left: 10px;">✕ delete</a>
</li>
<% end %>
</ul>
23 changes: 23 additions & 0 deletions views/delete_confirm.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<h2>Confirm Deletion</h2>

<% if @is_directory %>
<h3>Delete directory: <%= @key %></h3>
<p>The following files will be permanently deleted:</p>
<ul>
<% @affected_keys.each do |key| %>
<li><%= key %></li>
<% end %>
</ul>
<% else %>
<h3>Delete file: <%= @key %></h3>
<p>This file will be permanently deleted from both source and live buckets.</p>
<% end %>

<form method="POST" action="/delete-handler/<%= @key %>"
onsubmit="return confirm('Are you sure you want to delete this? This cannot be undone.');">
<input type="hidden" name="is_directory" value="<%= @is_directory %>">
<input type="submit" value="Delete permanently" style="color: red;">
</form>

<br>
<a href="/browse/<%= @parent_directory %>">Cancel and go back</a>
21 changes: 21 additions & 0 deletions views/upload.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
<% if @bulk %>
<h2>Bulk Upload Files</h2>
<hr>
<form method="POST"
action="/bulk-upload-handler/<%= @directory %>"
enctype="multipart/form-data">
<hr>
<br><input type="file" name="files[]" multiple>
<hr>
<br><label for="default_conversion">Use the default image conversion process:</label>
<input type="checkbox" id="default_conversion" name="default_conversion" checked>
<br><label for="convert_to_jpeg">Convert files to JPEG:</label>
<input type="checkbox" id="convert_to_jpeg" name="convert_to_jpeg">
<br><label for="allow_overwrite">Allow overwriting source files:</label>
<input type="checkbox" id="allow_overwrite" name="allow_overwrite">

<hr>
<input type="submit" value="Upload All">
</form>
<% else %>
<h2>Upload a file</h2>
<hr>
<form method="POST"
Expand All @@ -16,3 +36,4 @@
<hr>
<input type="submit" value="Upload">
</form>
<% end %>
3 changes: 3 additions & 0 deletions views/view.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
<a href="/edit/<%= @asset.key %>">
<h3>Edit this image</h3>
</a>
<a href="/delete/<%= @asset.key %>" style="color: red;">
<h3>Delete this image</h3>
</a>

<hr>
<h2>Current Live Image:</h2>
Expand Down