Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Plugins: provide plugin's auth rules to view hooks

Sets the current CanCan ability ruleset to the one from the plugin while
the plugin's view code is executing.
  • Loading branch information...
commit 198080ad2201856faa7fd57e0b41da7a706d0e4f 1 parent e9fcc64
@mikldt mikldt authored
View
43 app/controllers/application_controller.rb
@@ -13,20 +13,47 @@ def current_ability
end
# Allow views in the main application to do authorization
- # checks for plugins. This will be needed for plugin code
- # that is included via UI hooks.
+ # checks for plugins.
def use_plugin_ability(mod, &block)
+ switch_to_plugin_ability(mod)
+ yield
+ switch_to_main_app_ability
+ end
+
+ # Store the current ability (if defined) and switch to the ability
+ # class for the specified plugin, if it has one.
+ # Always call switch_to_main_app_ability when done.
+ # Used by ConcertoPlugin for rendering hooks, and by use_plugin_ability
+ # block above.
+ def switch_to_plugin_ability(mod)
@main_app_ability = @current_ability
@plugin_abilities = @plugin_abilities || {}
mod_sym = mod.name.to_sym
if @plugin_abilities[mod_sym].nil?
- ability = (mod.name+"::Ability").constantize
- @current_ability =
- @plugin_abilities[mod_sym] ||= ability.new(current_user)
+ begin
+ ability = (mod.name+"::Ability").constantize
+ rescue
+ ability = nil
+ end
+ if ability.nil?
+ # Presumably this plugin doesn't define its own rules, no biggie
+ logger.warn "ConcertoPlugin: use_plugin_ability: "+
+ "No Ability found for "+mod.name
+ else
+ @plugin_abilities[mod_sym] ||= ability.new(current_user)
+ @current_ability = @plugin_abilities[mod_sym]
+ end
+ else
+ @current_ability = @plugin_abilities[mod_sym]
end
- @current_ability = @plugin_abilities[mod_sym]
- yield
- @current_ability = @main_app_ability
+ end
+
+ # Revert to the main app ability after using a plugin ability
+ # (if it was defined).
+ # Used by ConcertoPlugin for rendering hooks, and by use_plugin_ability
+ # block above.
+ def switch_to_main_app_ability
+ @current_ability = @main_app_ability # it is okay if this is nil
end
# Expose a instance variable counting the number of pending submissions
View
18 app/models/concerto_plugin.rb
@@ -3,10 +3,10 @@
#
# It also includes the code that allows the rest of the application
# to interface to individual plugins, including initialization tasks
-# as well as controller and view hooks.
+# and controller/view hooks.
#
-# This code interfaces closely with lib/concerto/plugin_library.rb,
-# which can be included into engines to enable use of the Concerto
+# This code interfaces closely with lib/concerto/plugin_info.rb,
+# which gets instantiated in engines to enable use of the Concerto
# Plugin interface.
class ConcertoPlugin < ActiveRecord::Base
@@ -40,6 +40,11 @@ def engine
@engine ||= get_engine_from_module(module_name)
end
+ # Quick way to get the module constant
+ def mod
+ module_name.constantize
+ end
+
# Returns the instance of PluginInfo provided by the engine
# Note for simplicity we're not caching this info.
def plugin_info
@@ -105,6 +110,8 @@ def self.render_view_hook(context, hook_name)
ConcertoPlugin.enabled.each do |plugin|
if info = plugin.plugin_info
info.get_view_hooks(controller_name, hook_name).each do |hook|
+ # Make the authorization rules from the plugin available
+ context.controller.switch_to_plugin_ability(plugin.mod)
if hook[:type] == :partial
result += context.render :partial => hook[:hook]
elsif hook[:type] == :text
@@ -112,6 +119,8 @@ def self.render_view_hook(context, hook_name)
elsif hook[:type] == :proc
result += context.instance_eval(&hook[:hook])
end
+ # Cleanup
+ context.controller.switch_to_main_app_ability
result += "\n"
end
else
@@ -139,11 +148,8 @@ def self.install_callbacks(controller)
" for callbacks")
end
end
- logger.info "ConcertoPlugin: Callbacks for this controller listed below:"
- logger.info callbacks.to_yaml
callbacks.each do |callback|
controller.set_callback(callback[:name], callback[:filter_list], callback[:block])
end
- logger.info "Concerto_Plugin: Done with callbacks"
end
end
View
2  config/initializers/12-plugins.rb
@@ -20,7 +20,7 @@
mount_points = ConcertoPlugin.get_mount_points
if mount_points.is_a? Array
mount_points.each do |app|
- mount app[:rack_app] => "/" + app[:url_string], :as => app[:url_string]
+ mount app[:rack_app] => "/" + app[:url_string]
# e.g. mount ConcertoHardware::Engine => "/hardware"
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.