module Sinatra::StrongParams

Constants

VERSION

Public Class Methods

registered(app) click to toggle source
# File lib/sinatra/strong-params.rb, line 10
def self.registered(app)
  #
  # A way to whitelist parameters.
  #
  #   get '/', allows: [:id, :action] do
  #     erb :index
  #   end
  #
  # Modifies the parameters available in the request scope.
  # Stashes unmodified params in @_params
  #
  app.set(:allows) do |*passable|
    condition do
      unless @params.empty?
        @_params = @_params || @params # for safety
        globals  = settings.globally_allowed_parameters
        needed   = @_needed || []
        passable = (globals | passable | needed).map(&:to_sym) # make sure it's a symbol

        # Keep only the allowed parameters.
        @params = @params.delete_if do |param, _value|
          !passable.include?(param.to_sym)
        end
      end
    end
  end

  #
  # A way to require parameters
  #
  #   get '/', needs: [:id, :action] do
  #     erb :index
  #   end
  #
  # Does not modify the parameters available to the request scope.
  # Raises a RequiredParamMissing error if a needed param is missing
  #
  app.set(:needs) do |*needed|
    condition do
      needed     = needed.map(&:to_sym) # make sure it's a symbol
      @_needed   = needed
      sym_params = @params.dup

      # symbolize the keys so we know what we're looking at
      sym_params.keys.each do |key|
        sym_params[(key.to_sym rescue key) || key] = sym_params.delete(key)
      end

      missing_params = needed.select { |key| sym_params[key].nil? || sym_params[key].empty? }
      if missing_params.any?
        fail RequiredParamMissing, "#{settings.missing_parameter_message} #{missing_params.join(', ')}"
      end
    end
  end

  # These will always pass through the 'allows' method
  # and will be mapped to symbols. I often use [:redirect_to, :_csrf] here
  # because I always want them to pass through for later processing
  app.set :globally_allowed_parameters, []

  # The default message when RequiredParamMissing is raised.
  app.set :missing_parameter_message, 'One or more required parameters were missing:'

  # Change the default behavior for missing parameters by overriding this route.
  # For example...
  #
  #   error RequiredParamMissing do
  #     flash[:error] = env['sinatra.error'].message
  #     redirect back
  #   end
  #
  app.error RequiredParamMissing do
    [400, env['sinatra.error'].message]
  end
end