lib/condo.rb in condo-1.0.6 vs lib/condo.rb in condo-2.0.0
- old
+ new
@@ -1,54 +1,50 @@
+# encoding: utf-8
+
+require 'fog'
require 'condo/engine'
require 'condo/errors'
require 'condo/configuration'
module Condo
def self.included(base)
base.class_eval do
-
-
+
+
def new
- #
# Returns the provider that will be used for this file upload
resident = current_resident
- #
# Ensure parameters are correct
params.require(:file_size)
params.require(:file_name)
permitted = params.permit(:file_size, :file_name, :file_path)
@upload = {
file_size: permitted[:file_size].to_i,
file_name: @@callbacks[:sanitize_filename].call(permitted[:file_name])
}
@upload[:file_path] = @@callbacks[:sanitize_filepath].call(permitted[:file_path]) if permitted[:file_path]
-
+
valid, errors = instance_exec(@upload, &@@callbacks[:pre_validation]) # Ensure the upload request is valid before uploading
- if !!valid
- set_residence(nil, {:resident => resident, :params => @upload}) if condo_config.dynamic_provider_present?(@@namespace)
+ if valid
residence = current_residence
-
- render :json => {:residence => residence.name}
-
+
+ render json: {residence: residence.name}
elsif errors.is_a? Hash
- render :json => errors, :status => :not_acceptable
+ render json: errors, status: :not_acceptable
else
- render :nothing => true, :status => :not_acceptable
+ render nothing: true, status: :not_acceptable
end
end
-
+
def create
- #
# Check for existing upload or create a new one
# => mutually exclusive so can send back either the parts signature from show or a bucket creation signature and the upload_id
- #
resident = current_resident
-
- #
+
# Ensure parameters are correct
params.require(:file_size)
params.require(:file_name)
params.require(:file_id)
permitted = params.permit(:file_size, :file_name, :file_path, :file_id)
@@ -57,213 +53,214 @@
file_name: @@callbacks[:sanitize_filename].call(permitted[:file_name]),
file_id: permitted[:file_id],
user_id: resident
}
@upload[:file_path] = @@callbacks[:sanitize_filepath].call(permitted[:file_path]) if permitted[:file_path]
-
- #
+
# Check for existing uploads
upload = condo_backend.check_exists(@upload)
-
+
if upload.present?
- residence = set_residence(upload.provider_name, {
- :location => upload.provider_location,
- :upload => upload
- })
-
- #
+ residence = current_residence(upload)
+
# Return the parts or direct upload sig
- #
request = nil
if upload.resumable_id.present? && upload.resumable
request = residence.get_parts({
- :bucket_name => upload.bucket_name,
- :object_key => upload.object_key,
- :object_options => upload.object_options,
- :file_size => upload.file_size,
- :resumable_id => upload.resumable_id
+ bucket_name: upload.bucket_name,
+ object_key: upload.object_key,
+ object_options: upload.object_options,
+ file_size: upload.file_size,
+ resumable_id: upload.resumable_id
})
+
+ request[:part_list] = upload.part_list || []
+ request[:part_data] = upload.part_data if upload.part_data
else
request = residence.new_upload({
- :bucket_name => upload.bucket_name,
- :object_key => upload.object_key,
- :object_options => upload.object_options,
- :file_size => upload.file_size,
- :file_id => upload.file_id
+ bucket_name: upload.bucket_name,
+ object_key: upload.object_key,
+ object_options: upload.object_options,
+ file_size: upload.file_size,
+ file_id: upload.file_id
})
end
- render :json => request.merge(:upload_id => upload.id, :residence => residence.name)
+ render json: request.merge!({
+ upload_id: upload.id,
+ residence: residence.name
+ })
else
- #
# Create a new upload
- #
valid, errors = instance_exec(@upload, &@@callbacks[:pre_validation]) # Ensure the upload request is valid before uploading
-
-
+
if valid
- set_residence(nil, {:resident => resident, :params => @upload}) if condo_config.dynamic_provider_present?(@@namespace)
residence = current_residence
-
- #
+
# Build the request
- #
@upload.merge!({
bucket_name: (instance_eval &@@callbacks[:bucket_name]), # Allow the application to define a custom bucket name
object_key: instance_exec(@upload, &@@callbacks[:object_key]), # The object key should also be generated by the application
object_options: instance_exec(@upload, &@@callbacks[:object_options]) # Do we want to mess with any of the options?
})
request = residence.new_upload(@upload)
resumable = request[:type] == :chunked_upload
-
- #
+
# Save a reference to this upload in the database
# => This should throw an error on failure
- #
- upload = condo_backend.add_entry(@upload.merge!({:provider_name => residence.name, :provider_location => residence.location, :resumable => resumable}))
- render :json => request.merge!(:upload_id => upload.id, :residence => residence.name)
+ upload = condo_backend.add_entry(@upload.merge!({provider_name: residence.name, provider_location: residence.location, resumable: resumable}))
+ render json: request.merge!(upload_id: upload.id, residence: residence.name)
elsif errors.is_a? Hash
- render :json => errors, :status => :not_acceptable
+ render json: errors, status: :not_acceptable
else
- render :nothing => true, :status => :not_acceptable
+ render nothing: true, status: :not_acceptable
end
end
end
-
-
- #
+
# Authorization check all of these
- #
def edit
- #
# Get the signature for parts + final commit
- #
upload = current_upload
+
params.require(:part)
safe_params = params.permit(:part, :file_id)
-
+
if upload.resumable_id.present? && upload.resumable
- residence = set_residence(upload.provider_name, {:location => upload.provider_location, :upload => upload})
-
+ residence = current_residence(upload)
+
request = residence.set_part({
- :bucket_name => upload.bucket_name,
- :object_key => upload.object_key,
- :object_options => upload.object_options,
- :resumable_id => upload.resumable_id,
- :part => safe_params[:part], # part may be called 'finish' for commit signature
- :file_size => upload.file_size,
- :file_id => safe_params[:file_id]
+ bucket_name: upload.bucket_name,
+ object_key: upload.object_key,
+ object_options: upload.object_options,
+ resumable_id: upload.resumable_id,
+ # part may be called 'finish' for commit signature
+ part: safe_params[:part],
+ file_size: upload.file_size,
+ file_id: safe_params[:file_id]
})
-
- render :json => request.merge!(:upload_id => upload.id)
+
+ render json: request.merge!(upload_id: upload.id)
else
- render :nothing => true, :status => :not_acceptable
+ render nothing: true, status: :not_acceptable
end
end
-
-
+
+
def update
- #
# Provide the upload id after creating a resumable upload (may not be completed)
# => We then provide the first part signature
#
# OR
#
# Complete an upload
- #
- if params[:resumable_id]
- upload = current_upload
+ upload = current_upload
+
+ safe = params.permit(:resumable_id, {part_list: []}, {part_data: [
+ :md5,
+ :size_bytes,
+ :path,
+ :part
+ ]})
+ part_list = safe[:part_list]
+ resumable_id = safe[:resumable_id]
+
+ if resumable_id || part_list
if upload.resumable
- @current_upload = upload.update_entry :resumable_id => params.permit(:resumable_id)[:resumable_id]
- edit
+ if part_list
+ upload.part_list = part_list || []
+
+ # We incrementally update this as it might otherwise contain
+ # sum(1 -> 10,000) parts over the time of the upload
+ # (as is the case with the largest file amazon supports)
+ if safe[:part_data]
+ upload.part_data ||= {}
+ safe[:part_data].each do |part|
+ upload.part_data[part[:part]] = part
+ end
+ end
+ end
+
+ upload.resumable_id = resumable_id if resumable_id
+ upload.save!
+
+ if params[:part_update]
+ render nothing: true
+ else
+ @current_upload = upload
+
+ # Render is called from edit
+ edit
+ end
else
- render :nothing => true, :status => :not_acceptable
+ render nothing: true, status: :not_acceptable
end
- else
- response = instance_exec current_upload, &@@callbacks[:upload_complete]
+
+ else # We are completeing the upload
+ response = instance_exec upload, &@@callbacks[:upload_complete]
if response
- render :nothing => true
+ render nothing: true
else
- render :nothing => true, :status => :not_acceptable
+ render nothing: true, status: :not_acceptable
end
end
end
-
-
+
def destroy
- #
# Delete the file from the cloud system - the client is not responsible for this
- #
response = instance_exec current_upload, &@@callbacks[:destroy_upload]
if response
- render :nothing => true
+ render nothing: true
else
- render :nothing => true, :status => :not_acceptable
+ render nothing: true, status: :not_acceptable
end
end
-
-
+
+
protected
-
-
- #
- # A before filter can be used to select the cloud provider for the current user
- # Otherwise the dynamic residence can be used when users are define their own storage locations
- #
- def set_residence(name, options = {})
- options[:namespace] = @@namespace
- @current_residence = condo_config.set_residence(name, options)
+
+
+ def current_residence(upload = nil)
+ @current_residence ||= instance_exec(condo_config, current_resident, upload, &@@callbacks[:select_residence])
end
-
- def current_residence
- @current_residence ||= condo_config.residencies[0]
- end
-
+
def current_upload
return @current_upload if @current_upload
safe_params = params.permit(:upload_id, :id)
- @current_upload = condo_backend.check_exists({:user_id => current_resident, :upload_id => (safe_params[:upload_id] || safe_params[:id])}).tap do |object| #current_residence.name && current_residence.location && resident.id.exists?
+ # current_residence.name && current_residence.location && resident.id.exists?
+ @current_upload = condo_backend.check_exists({user_id: current_resident, upload_id: (safe_params[:upload_id] || safe_params[:id])}).tap do |object|
raise Condo::Errors::NotYourPlace unless object.present?
end
end
-
+
def current_resident
- @current_resident ||= (instance_eval &@@callbacks[:resident_id]).tap do |object| # instance_exec for params
+ # instance_exec for params
+ @current_resident ||= (instance_eval &@@callbacks[:resident_id]).tap do |object|
raise Condo::Errors::LostTheKeys unless object.present?
end
end
-
+
def condo_backend
- Condo::Store
+ ::Condo::Store
end
-
+
def condo_config
- Condo::Configuration.instance
+ ::Condo::Configuration
end
-
-
- #
+
+
# Defines the default callbacks
- #
(@@callbacks ||= {}).merge! Condo::Configuration.callbacks
- @@namespace ||= :global
-
-
+
def self.condo_callback(name, callback = nil, &block)
callback ||= block
if callback.respond_to?(:call)
@@callbacks[name.to_sym] = callback
else
raise ArgumentError, 'No callback provided'
end
end
-
-
- def self.condo_namespace(name)
- @@namespace = name.to_sym
- end
-
end
end
end