lib/condo.rb in condo-1.0.4 vs lib/condo.rb in condo-1.0.6
- old
+ new
@@ -1,269 +1,269 @@
-require 'condo/engine'
-require 'condo/errors'
-require 'condo/configuration'
-
-
-#Dir[File.join('condo', 'strata', '*.rb')].each do |file| # Using autoload_paths now
-# require file[0..-4] # Removes the .rb ext name
-#end
-
-
-module Condo
-
- #
- # TODO:: Simplify the parameters passed in
- # Object options should be set at the application level
- # The application can set these based on the custom params.
- # Have an instance member that holds the parameter set: @upload
- #
- def self.included(base)
- base.class_eval do
-
-
- def new
- #
- # Returns the provider that will be used for this file upload
- #
- resident = current_resident
-
- @upload ||= {}
- @upload[:file_size] = params[:file_size].to_i
- @upload[:file_name] = (instance_eval &@@callbacks[:sanitize_filename])
- @upload[:file_path] = (instance_eval &@@callbacks[:sanitize_filepath]) if params[:file_path]
-
- valid, errors = instance_eval &@@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
-
- render :json => {:residence => residence.name}
-
- elsif errors.is_a? Hash
- render :json => errors, :status => :not_acceptable
- else
- 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
-
- @upload = {}
- @upload[:file_size] = params[:file_size].to_i
- @upload[:file_id] = params[:file_id]
- @upload[:file_name] = (instance_eval &@@callbacks[:sanitize_filename])
- @upload[:file_path] = (instance_eval &@@callbacks[:sanitize_filepath]) if params[:file_path]
-
- upload = condo_backend.check_exists({
- :user_id => resident,
- :file_name => @upload[:file_name],
- :file_size => @upload[:file_size],
- :file_id => @upload[:file_id]
- })
-
- if upload.present?
- residence = set_residence(upload.provider_name, {
- :location => upload.provider_location,
- :upload => upload
- })
-
- #
- # Return the parts or direct upload sig
- #
- request = nil
- if upload.resumable_id.present? && upload.resumable
- upload.object_options[:parameters] = {} || params[:parameters] # May need to request the next set of parts
- request = residence.get_parts({
- :bucket_name => upload.bucket_name,
- :object_key => upload.object_key,
- :object_options => upload.object_options,
- :resumable_id => upload.resumable_id
- })
- 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
- })
- end
-
- render :json => request.merge(:upload_id => upload.id, :residence => residence.name)
- else
- #
- # Create a new upload
- #
- valid, errors = instance_eval &@@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
- #
- request = residence.new_upload(@upload.merge!({
- :bucket_name => (instance_eval &@@callbacks[:bucket_name]), # Allow the application to define a custom bucket name
- :object_key => (instance_eval &@@callbacks[:object_key]), # The object key should also be generated by the application
- :object_options => (instance_eval &@@callbacks[:object_options]) # Do we want to mess with any of the options?
- }))
- 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!({:user_id => resident, :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
- else
- render :nothing => true, :status => :not_acceptable
- end
- end
- end
-
-
- #
- # Authorisation check all of these
- #
- def edit
- #
- # Get the signature for parts + final commit
- #
- upload = current_upload
-
- if upload.resumable_id.present? && upload.resumable
- residence = set_residence(upload.provider_name, {:location => upload.provider_location, :upload => 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 => params[:part], # part may be called 'finish' for commit signature
- :file_id => params[:file_id]
- })
-
- render :json => request.merge!(:upload_id => upload.id)
- else
- 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
- if upload.resumable
- @current_upload = upload.update_entry :resumable_id => params[:resumable_id]
- edit
- else
- render :nothing => true, :status => :not_acceptable
- end
- else
- response = instance_exec current_upload, &@@callbacks[:upload_complete]
- if !!response
- current_upload.remove_entry
- render :nothing => true
- else
- 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
- current_upload.remove_entry
- render :nothing => true
- else
- 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)
- end
-
- def current_residence
- @current_residence ||= condo_config.residencies[0]
- end
-
- def current_upload
- @current_upload ||= condo_backend.check_exists({:user_id => current_resident, :upload_id => (params[:upload_id] || params[:id])}).tap do |object| #current_residence.name && current_residence.location && resident.id.exists?
- 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
- raise Condo::Errors::LostTheKeys unless object.present?
- end
- end
-
- def condo_backend
- Condo::Store
- end
-
- def condo_config
- Condo::Configuration.instance
- end
-
-
- #
- # Defines the default callbacks
- #
- (@@callbacks ||= {}).merge! Condo::Configuration.callbacks
- @@namespace ||= :global
-
-
- def self.set_callback(name, callback = nil, &block)
- if callback.is_a?(Proc)
- @@callbacks[name.to_sym] = callback
- elsif block.present?
- @@callbacks[name.to_sym] = block
- else
- raise ArgumentError, 'Condo callbacks must be defined with a Proc or Proc (lamba) object present'
- end
- end
-
-
- def self.set_namespace(name)
- @@namespace = name.to_sym
- end
-
- end
- end
-
-
-end
+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)
+ residence = current_residence
+
+ render :json => {:residence => residence.name}
+
+ elsif errors.is_a? Hash
+ render :json => errors, :status => :not_acceptable
+ else
+ 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)
+ @upload = {
+ file_size: permitted[:file_size].to_i,
+ 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
+ })
+
+ #
+ # 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
+ })
+ 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
+ })
+ end
+
+ 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)
+
+ elsif errors.is_a? Hash
+ render :json => errors, :status => :not_acceptable
+ else
+ 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})
+
+ 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]
+ })
+
+ render :json => request.merge!(:upload_id => upload.id)
+ else
+ 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
+ if upload.resumable
+ @current_upload = upload.update_entry :resumable_id => params.permit(:resumable_id)[:resumable_id]
+ edit
+ else
+ render :nothing => true, :status => :not_acceptable
+ end
+ else
+ response = instance_exec current_upload, &@@callbacks[:upload_complete]
+ if response
+ render :nothing => true
+ else
+ 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
+ else
+ 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)
+ 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?
+ 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
+ raise Condo::Errors::LostTheKeys unless object.present?
+ end
+ end
+
+ def condo_backend
+ Condo::Store
+ end
+
+ def condo_config
+ Condo::Configuration.instance
+ 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