module Incline::Extensions::ActionControllerBase
Adds some extra functionality to the base controller definition.
Public Class Methods
Enforces SSL and catches Incline::NotLoggedIn exceptions.
# File lib/incline/extensions/action_controller_base.rb, line 172 def self.included(base) base.extend ClassMethods base.class_eval do # Force SSL under production environments unless allow_http_for_request returns true. if Rails.env.production? force_ssl unless: :allow_http_for_request? end # Process user authorization for all actions except the GET/POST api actions. # These get to be authorized once the actual action is selected. before_action :valid_user?, except: [ :api ] undef process_action ## # Override the default to enable auto-api behavior if desired. def process_action(method_name, *args) #:nodoc: if self.class.auto_api? unless process_api_action(false, nil) super method_name, *args end else super method_name, *args end end rescue_from ::Incline::NotLoggedIn do |exception| flash[:info] = exception.message store_location redirect_to(incline.login_url) end end end
Public Instance Methods
A redirects to a previously stored location or to the default location.
Usually this will be used to return to an action after a user logs in.
# File lib/incline/extensions/action_controller_base.rb, line 230 def redirect_back_or(default) redirect_to session[:forwarding_url] || default session.delete :forwarding_url end
Renders the view as a CSV file.
Set the filename
you would like to provide to the client, or leave it nil to use the action name. Set the view_name
you would like to render, or leave it nil to use the action name.
# File lib/incline/extensions/action_controller_base.rb, line 213 def render_csv(filename = nil, view_name = nil) filename ||= params[:action] view_name ||= params[:action] filename.downcase! filename += '.csv' unless filename[-4..-1] == '.csv' headers['Content-Type'] = 'text/csv' headers['Content-Disposition'] = "attachment; filename=\"#{filename}\"" render view_name, layout: false end
Stores the current URL to be used with redirect_back_or
.
# File lib/incline/extensions/action_controller_base.rb, line 237 def store_location session[:forwarding_url] = request.url if request.get? end
Protected Instance Methods
Determines if the current request can be allowed with an anonymous user.
Overridden by require_admin_for_request? Implied by require_anon_for_request?
# File lib/incline/extensions/action_controller_base.rb, line 371 def allow_anon_for_request? #:doc: self.class.allow_anon_for? params[:action] end
Determines if the current request can be allowed via HTTP (non-SSL).
# File lib/incline/extensions/action_controller_base.rb, line 362 def allow_http_for_request? #:doc: self.class.allow_http_for? params[:action] end
Is the current request an inline request?
JSON requests are always considered inline, otherwise we check to see if the “inline” parameter is set to a true value.
Primarily this would be used to strip the layour from rendered content.
# File lib/incline/extensions/action_controller_base.rb, line 356 def inline_request? json_request? || params[:inline].to_bool end
Is the current request for JSON data?
Redirects are generally bad when JSON data is requested. For instance a `create` request in JSON format should return data, not redirect to `show`.
# File lib/incline/extensions/action_controller_base.rb, line 346 def json_request? #:doc: request.format.to_s =~ /^(application\/)?json$/i end
This method maps the requested action into the actual action performed.
By default, the requested action is returned. If for some reason you want to use a different action in your API, override this method in your controller and map the actions as appropriate.
The actions you can expect to translate are 'index', 'new', 'show', and 'edit' for GET requests, and 'create', 'update', and 'destroy' for POST requests. They will be string values or nil, they will not be symbols.
The default behavior causes the API to “fall through” to your standard controller methods.
The API is accessed by either a POST or a GET request that specifies an `action` parameter. The action gets translated to the acceptable actions listed above and then run through this method for translation.
# File lib/incline/extensions/action_controller_base.rb, line 261 def map_api_action(requested_action) #:doc: requested_action end
Determines if the current request requires a system administrator.
Overrides all other access requirements.
# File lib/incline/extensions/action_controller_base.rb, line 379 def require_admin_for_request? #:doc: self.class.require_admin_for? params[:action] end
Determines if the current request requires an anonymous user.
Overridden by require_admin_for_request? Implies allow_anon_for_request?
# File lib/incline/extensions/action_controller_base.rb, line 388 def require_anon_for_request? #:doc: self.class.require_anon_for? params[:action] end
Private Instance Methods
# File lib/incline/extensions/action_controller_base.rb, line 447 def process_api_action(raise_on_invalid_action = true, default_get_action = 'index') api_action = map_api_action( if request.post? # A post request can create, update, or destroy. # In addition we allow index to post since DataTables can send quite a bit of data with server-side # processing. # The post action can be provided as a query parameter or a form parameter with the form parameter # taking priority. { nil => 'index', 'list' => 'index', 'index' => 'index', 'new' => 'create', 'create' => 'create', 'edit' => 'update', 'update' => 'update', 'remove' => 'destroy', 'destroy' => 'destroy' }[request.request_parameters.delete('action') || request.query_parameters.delete('action')] elsif request.get? # For the most part, these shouldn't be used except for maybe index and show. # The new and edit actions could be used if for some reason you need to supply data to the ajax form # calling these actions, e.g. - a list of locations. # Datatables Editor does not use any of them. # Datatables will simple be requesting the index action in JSON format. # To remain consistent though, you can use '?action=list' to perform the same feat. { 'list' => 'index', 'index' => 'index', 'new' => 'new', 'show' => 'show', 'edit' => 'edit' }[request.query_parameters.delete('action')] || default_get_action else nil end ) if api_action # Datatables Editor sends the 'data' in the 'data' parameter. # We simple want to move that up a level so `params[:data][:user][:name]` becomes `params[:user][:name]`. data = request.params.delete('data') unless data.blank? # get the first entry in the hash. id, item = data.first # if the id is in AAAAA_NNN format, then we can extract the ID from it. if id.include?('_') id,_, item_id = id.rpartition('_') params[:id] = item_id.to_i end # merge the item data into the params array. params.merge!(id => item) end # since we are processing for an API request, we should return JSON. request.format = :json # finally, we'll start over on processing the stack. # This should ensure the appropriate `before_action` filters are called for the new action. process api_action else # raise an error. raise Incline::InvalidApiCall, 'Invalid API Action' if raise_on_invalid_action nil end end
# File lib/incline/extensions/action_controller_base.rb, line 522 def raise_not_logged_in(message, log_message = nil) log_authorize_failure message, log_message raise Incline::NotLoggedIn.new(message) end
Validates that the current user is authorized for the current request.
This method is called for every action except the :api action. For the :api action, this method will not be called until the actual requested action is performed.
One of four scenarios are possible:
-
If the
require_admin
method applies to the current action, then a system administrator must be logged in.-
If a nobody is logged in, then the user will be redirected to the login url.
-
If a system administrator is logged in, then access is granted.
-
Non-system administrators will be redirected to the root url.
-
-
If the
require_anon
method applies to the current action, then a user cannot be logged in.-
If a user is logged in, a warning message is set and the user is redirected to their account.
-
If no user is logged in, then access is granted.
-
-
If the
allow_anon
method applies to the current action, then access is granted. -
The action doesn't require a system administrator, but does require a valid user to be logged in.
-
If nobody is logged in, then the user will be redirected to the login url.
-
If a system administrator is logged in, then access is granted.
-
If the action doesn't have any required permissions, then access is granted to any logged in user.
-
If the action has required permissions and the logged in user shares at least one, then access is granted.
-
Users without at least one required permission are redirected to the root url.
-
Two of the scenarios are configured at design time. If you use require_admin
or allow_anon
, they cannot be changed at runtime. The idea is that anything that allows anonymous access will always allow anonymous access during runtime and anything that requires admin access will always require admin access during runtime.
The third scenario is what would be used by most actions. Using the admin
controller, which requires admin access, you can customize the permissions required for each available route. Using the users
controller, admins can assign permissions to other users.
# File lib/incline/extensions/action_controller_base.rb, line 426 def valid_user? #:doc: if require_admin_for_request? authorize! true elsif require_anon_for_request? if logged_in? flash[:warning] = 'The specified action cannot be performed while logged in.' redirect_to incline.user_path(current_user) end elsif allow_anon_for_request? true else action = Incline::ActionSecurity.valid_items[self.class.controller_path, params[:action]] if action && action.groups.count > 0 authorize! action.groups.pluck(:name) else authorize! end end end