app/controllers/token_action/tokens_controller.rb
require_dependency 'token_action/application_controller'
module TokenAction
class TokensController < ApplicationController
def redeem
@token = TokenAction::Token.to_adapter.find_first(token: params[:token])
if @token
begin
# Do this in the controller's scope to allow access to request methods.
ActiveSupport::Inflector.constantize(@token.kind).redeem_token(*@token.args)
redirect_to success_url, notice: translate(:success)
rescue => e
key = ActiveSupport::Inflector.underscore(e.class.name).gsub('/', I18n.default_separator)
logger.warn "TokenAction failed to perform the action for the token '#{params[:token]}': #{e.message}"
redirect_to failure_url, alert: translate(key, :failure)
end
else
logger.info "TokenAction failed to find the token '#{params[:token]}'"
redirect_to failure_url, alert: translate(:not_found)
end
end
private
# Returns a translation.
#
# @param [Array] args translation keys
# @return [String] a translation
def translate(*args)
path = params[:path].gsub('/', I18n.default_separator)
keys = []
# Respect the order of precedence described in the readme.
args.each do |key|
[path, :default].each do |scope|
keys << [:token_action, :tokens, scope, key]
end
end
keys.map! do |key|
key.join(I18n.default_separator).to_sym
end
key, *default = *keys
I18n.translate(key, default: default)
end
# Returns the success URL.
#
# @return [String] a URL
def success_url
redirect_url([@token && @token.success_url, TokenAction.success_url])
end
# Returns the failure URL.
#
# @return [String] a URL
def failure_url
redirect_url([@token && @token.failure_url, TokenAction.failure_url])
end
# Returns the routeable URL with the highest preference.
#
# @param [Array<String>] a list of URLs in order of preference
# @return [String] the routable URL with the highest preference
def redirect_url(urls)
urls.find do |url|
url.present? && routable?(url)
end || main_app.root_path
end
# Returns whether a path is routable.
#
# @param [String] path a path
# @return [Boolean] whether the path is routable
def routable?(path)
!!Rails.application.routes.recognize_path(path, method: :get)
rescue ActionController::RoutingError
false
end
end
end