module Symphonia module ControllerExtensions extend ActiveSupport::Concern included do class Unauthorized < Exception; end before_action :current_user, :menu_item before_action :set_default_locale # force_ssl if: -> {Rails.env.production? && User.current.ssl?} add_flash_types :notice add_flash_types :info add_flash_types :warning add_flash_types :error rescue_from ::ActiveRecord::RecordNotFound do render_404 end rescue_from Unauthorized do render_403 end helper_method :current_user end def back_url url = params[:back_url] if url.nil? && (referer = request.env['HTTP_REFERER']) url = CGI.unescape(referer.to_s) end url end # def redirect_back_or_default(default, options={}) # back_url = params[:back_url].to_s # if back_url.present? # begin # uri = URI.parse(back_url) # # do not redirect user to another host or to the login or register page # if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)}) # redirect_to(back_url) # return # end # rescue URI::InvalidURIError # logger.warn("Could not redirect to invalid URL #{back_url}") # # redirect to default # end # elsif options[:referer] # redirect_to_referer_or default # return # end # redirect_to default, options # false # end # Redirects to the request referer if present, redirects to args or call block otherwise. def redirect_to_referer_or(*args, &block) redirect_to :back rescue ::ActionController::RedirectBackError if args.any? redirect_to *args elsif block_given? block.call else raise "#redirect_to_referer_or takes arguments or a block" end end # private def set_locale client_lang = Array(params.fetch(:locale, nil).presence || session[:locale].presence || request.env['HTTP_ACCEPT_LANGUAGE'].to_s.split(',').collect { |l| l.scan(/^[a-z]{2}/) }.flatten) client_lang.unshift current_user.language if current_user.language @client_lang = client_lang.detect { |l| I18n.available_locales.include?(l.to_sym) } I18n.locale = (@client_lang || I18n.default_locale) session[:locale] = I18n.locale logger.debug "* Locale set to '#{I18n.locale}'" end def set_default_locale if (enforce_default = Symphonia.config.default_locale) I18n.locale = enforce_default end end # protected def login_require(format = nil) if current_user.nil? || !current_user.logged_in? respond_to do |format| format.html do store_location redirect_to symphonia.login_path, flash: { error: t(:text_login_require) } end format.json { render json: { errors: 'You must be logged in to access this endpoint' }, status: 401 } format.any { head 401 } end return false end true end alias_method :require_login, :login_require alias_method :require_user, :login_require def admin_require return unless login_require unless current_user.admin? render_403 return false end end alias_method :require_admin, :admin_require def render_403 respond_to do |format| format.html { render template: 'common/403', message: :notice_not_authorized, status: 403 } format.js { render plain: "alert('#{t :text_access_deny}')", message: :notice_not_authorized, status: 403 } format.any { head 403, message: :notice_not_authorized } end end def render_404 respond_to do |format| format.html { render template: 'common/404', message: :notice_page_not_found, status: 404 } format.any { head 404, message: :not_found } end end # Renders a 200 response for successful updates or deletions via the API def render_api_ok head :ok end # Renders a head API response def render_api_head(status) head status end def menu_item(item = nil) @menu_item = (item || controller_name) end def current_user_session return @current_user_session if defined?(@current_user_session) @current_user_session = UserSession.find end def current_user return (Symphonia::User.current ||= @current_user) if defined?(@current_user) @current_user = current_user_session && current_user_session.user Symphonia::User.current = @current_user || Symphonia::User::Anonymous.new end def authorize if Symphonia::User.current.authorize?(controller_name, action_name) return true else if Symphonia::User.current.logged_in? raise Unauthorized else respond_to do |format| format.html do return redirect_to(symphonia.login_path(back_url: request.path), error: t(:text_error_login_required)) end format.any { return head 401 } end end end raise Unauthorized end def handle_unverified_request # raise an exception fail ActionController::InvalidAuthenticityToken # or destroy session, redirect if current_user_session current_user_session.destroy end redirect_to main_app.root_url end def store_location session[:return_to] = request.url end def redirect_back_or_default(default, options = {}) options ||= {} redirect_to(params[:back_url] || default, options) end end end