Revision 007bf254
Added by Shimon Shtein over 7 years ago
app/controllers/concerns/foreman/controller/action_permission_dsl.rb | ||
---|---|---|
module Foreman::Controller::ActionPermissionDsl
|
||
extend ActiveSupport::Concern
|
||
|
||
included do |klass|
|
||
klass.class_attribute :action_permissions
|
||
end
|
||
|
||
module ClassMethods
|
||
def define_action_permission(actions, permission)
|
||
self.action_permissions ||= {}
|
||
# for single action case
|
||
[actions].flatten.each do |action|
|
||
self.action_permissions[action] = permission
|
||
end
|
||
end
|
||
end
|
||
|
||
def action_permission
|
||
action_permissions[params[:action]] || super
|
||
end
|
||
end
|
app/controllers/concerns/foreman/controller/puppet/hosts_controller_extensions.rb | ||
---|---|---|
module Foreman::Controller::Puppet::HostsControllerExtensions
|
||
extend ActiveSupport::Concern
|
||
|
||
PUPPETMASTER_ACTIONS=[ :externalNodes, :lookup ]
|
||
PUPPET_AJAX_REQUESTS=%w{hostgroup_or_environment_selected puppetclass_parameters}
|
||
|
||
MULTIPLE_EDIT_ACTIONS = %w(select_multiple_environment update_multiple_environment
|
||
select_multiple_puppet_proxy update_multiple_puppet_proxy
|
||
select_multiple_puppet_ca_proxy update_multiple_puppet_ca_proxy)
|
||
PUPPET_MULTIPLE_ACTIONS = %w(multiple_puppetrun update_multiple_puppetrun) + MULTIPLE_EDIT_ACTIONS
|
||
included do
|
||
add_smart_proxy_filters PUPPETMASTER_ACTIONS, :features => ['Puppet']
|
||
alias_method :find_resource_for_puppet_host_extensions, :find_resource
|
||
alias_method :ajax_request_for_puppet_host_extensions, :ajax_request
|
||
|
||
before_action :ajax_request_for_puppet_host_extensions, :only => PUPPET_AJAX_REQUESTS
|
||
before_action :find_resource_for_puppet_host_extensions, :only => [:puppetrun]
|
||
before_action :taxonomy_scope_for_puppet_host_extensions, :only => PUPPET_AJAX_REQUESTS
|
||
before_action :find_multiple_for_puppet_host_extensions, :only => PUPPET_MULTIPLE_ACTIONS
|
||
before_action :validate_multiple_puppet_proxy, :only => :update_multiple_puppet_proxy
|
||
before_action :validate_multiple_puppet_ca_proxy, :only => :update_multiple_puppet_ca_proxy
|
||
|
||
define_action_permission ['puppetrun', 'multiple_puppetrun', 'update_multiple_puppetrun'], :puppetrun
|
||
define_action_permission MULTIPLE_EDIT_ACTIONS, :edit
|
||
|
||
set_callback :set_class_variables, :after, :set_puppet_class_variables
|
||
end
|
||
|
||
def hostgroup_or_environment_selected
|
||
Taxonomy.as_taxonomy @organization, @location do
|
||
if params['host']['environment_id'].present? || params['host']['hostgroup_id'].present?
|
||
render :partial => 'puppetclasses/class_selection', :locals => {:obj => (refresh_host)}
|
||
else
|
||
logger.info "environment_id or hostgroup_id is required to render puppetclasses"
|
||
end
|
||
end
|
||
end
|
||
|
||
def puppetclass_parameters
|
||
Taxonomy.as_taxonomy @organization, @location do
|
||
render :partial => "puppetclasses/classes_parameters", :locals => { :obj => refresh_host}
|
||
end
|
||
end
|
||
|
||
def multiple_puppetrun
|
||
deny_access unless Setting[:puppetrun]
|
||
end
|
||
|
||
def update_multiple_puppetrun
|
||
return deny_access unless Setting[:puppetrun]
|
||
if @hosts.map(&:puppetrun!).uniq == [true]
|
||
notice _("Successfully executed, check reports and/or log files for more details")
|
||
else
|
||
error _("Some or all hosts execution failed, Please check log files for more information")
|
||
end
|
||
redirect_back_or_to hosts_path
|
||
end
|
||
|
||
def select_multiple_environment
|
||
end
|
||
|
||
def update_multiple_environment
|
||
# simple validations
|
||
if (params[:environment].nil?) || (id=params["environment"]["id"]).nil?
|
||
error _('No environment selected!')
|
||
redirect_to(select_multiple_environment_hosts_path)
|
||
return
|
||
end
|
||
|
||
ev = Environment.find_by_id(id)
|
||
|
||
#update the hosts
|
||
@hosts.each do |host|
|
||
host.environment = (id == 'inherit' && host.hostgroup.present?) ? host.hostgroup.environment : ev
|
||
host.save(:validate => false)
|
||
end
|
||
|
||
notice _('Updated hosts: changed environment')
|
||
redirect_back_or_to hosts_path
|
||
end
|
||
|
||
def environment_from_param
|
||
# simple validations
|
||
if (params[:environment].nil?) || (id=params["environment"]["id"]).nil?
|
||
error _('No environment selected!')
|
||
redirect_to(select_multiple_environment_hosts_path)
|
||
return
|
||
end
|
||
|
||
id
|
||
end
|
||
|
||
def get_environment_id(env_params)
|
||
env_params['id'] if env_params
|
||
end
|
||
|
||
def get_environment_for(host, id)
|
||
if id == 'inherit' && host.hostgroup.present?
|
||
host.hostgroup.environment
|
||
else
|
||
Environment.find_by_id(id)
|
||
end
|
||
end
|
||
|
||
def validate_multiple_puppet_proxy
|
||
validate_multiple_proxy(select_multiple_puppet_proxy_hosts_path)
|
||
end
|
||
|
||
def validate_multiple_puppet_ca_proxy
|
||
validate_multiple_proxy(select_multiple_puppet_ca_proxy_hosts_path)
|
||
end
|
||
|
||
def validate_multiple_proxy(redirect_path)
|
||
if params[:proxy].nil? || (proxy_id = params[:proxy][:proxy_id]).nil?
|
||
error _('No proxy selected!')
|
||
redirect_to(redirect_path)
|
||
return false
|
||
end
|
||
|
||
if !proxy_id.blank? && !SmartProxy.find_by_id(proxy_id)
|
||
error _('Invalid proxy selected!')
|
||
redirect_to(redirect_path)
|
||
return false
|
||
end
|
||
end
|
||
|
||
def update_multiple_proxy(proxy_type, host_update_method)
|
||
proxy_id = params[:proxy][:proxy_id]
|
||
if proxy_id
|
||
proxy = SmartProxy.find_by_id(proxy_id)
|
||
else
|
||
proxy = nil
|
||
end
|
||
|
||
failed_hosts = {}
|
||
|
||
@hosts.each do |host|
|
||
begin
|
||
host.send(host_update_method, proxy)
|
||
host.save!
|
||
rescue => error
|
||
failed_hosts[host.name] = error
|
||
message = _('Failed to set %{proxy_type} proxy for %{host}.') % {:host => host, :proxy_type => proxy_type}
|
||
Foreman::Logging.exception(message, error)
|
||
end
|
||
end
|
||
|
||
if failed_hosts.empty?
|
||
if proxy
|
||
notice _('The %{proxy_type} proxy of the selected hosts was set to %{proxy_name}.') % {:proxy_name => proxy.name, :proxy_type => proxy_type}
|
||
else
|
||
notice _('The %{proxy_type} proxy of the selected hosts was cleared.') % {:proxy_type => proxy_type}
|
||
end
|
||
else
|
||
error n_("The %{proxy_type} proxy could not be set for host: %{host_names}.",
|
||
"The %{proxy_type} puppet ca proxy could not be set for hosts: %{host_names}.",
|
||
failed_hosts.count) % {:proxy_type => proxy_type, :host_names => failed_hosts.map {|h, err| "#{h} (#{err})"}.to_sentence}
|
||
end
|
||
redirect_back_or_to hosts_path
|
||
end
|
||
|
||
def handle_proxy_messages(errors, proxy, proxy_type)
|
||
if errors.empty?
|
||
if proxy
|
||
notice _('The %{proxy_type} proxy of the selected hosts was set to %{proxy_name}.') % {:proxy_name => proxy.name, :proxy_type => proxy_type}
|
||
else
|
||
notice _('The %{proxy_type} proxy of the selected hosts was cleared.') % {:proxy_type => proxy_type}
|
||
end
|
||
else
|
||
error n_("The %{proxy_type} proxy could not be set for host: %{host_names}.",
|
||
"The %{proxy_type} puppet ca proxy could not be set for hosts: %{host_names}.",
|
||
errors.count) % {:proxy_type => proxy_type, :host_names => errors.map {|h, err| "#{h} (#{err})"}.to_sentence}
|
||
end
|
||
end
|
||
|
||
def select_multiple_puppet_proxy
|
||
end
|
||
|
||
def update_multiple_puppet_proxy
|
||
update_multiple_proxy(_('Puppet'), :puppet_proxy=)
|
||
end
|
||
|
||
def select_multiple_puppet_ca_proxy
|
||
end
|
||
|
||
def update_multiple_puppet_ca_proxy
|
||
update_multiple_proxy(_('Puppet CA'), :puppet_ca_proxy=)
|
||
end
|
||
|
||
def set_puppet_class_variables
|
||
@environment = @host.environment
|
||
end
|
||
|
||
def taxonomy_scope_for_puppet_host_extensions
|
||
taxonomy_scope
|
||
end
|
||
|
||
def find_multiple_for_puppet_host_extensions
|
||
find_multiple
|
||
end
|
||
end
|
app/controllers/hosts_controller.rb | ||
---|---|---|
class HostsController < ApplicationController
|
||
define_callbacks :set_class_variables
|
||
|
||
include Foreman::Controller::ActionPermissionDsl
|
||
include ScopesPerAction
|
||
include Foreman::Controller::HostDetails
|
||
include Foreman::Controller::AutoCompleteSearch
|
||
include Foreman::Controller::TaxonomyMultiple
|
||
include Foreman::Controller::SmartProxyAuth
|
||
include Foreman::Controller::Parameters::Host
|
||
include Foreman::Controller::Puppet::HostsControllerExtensions
|
||
|
||
PUPPETMASTER_ACTIONS=[ :externalNodes, :lookup ]
|
||
SEARCHABLE_ACTIONS= %w[index active errors out_of_sync pending disabled ]
|
||
AJAX_REQUESTS=%w{compute_resource_selected hostgroup_or_environment_selected current_parameters puppetclass_parameters process_hostgroup process_taxonomy review_before_build scheduler_hint_selected}
|
||
AJAX_REQUESTS=%w{compute_resource_selected current_parameters process_hostgroup process_taxonomy review_before_build scheduler_hint_selected}
|
||
BOOT_DEVICES={ :disk => N_('Disk'), :cdrom => N_('CDROM'), :pxe => N_('PXE'), :bios => N_('BIOS') }
|
||
MULTIPLE_ACTIONS = %w(multiple_parameters update_multiple_parameters select_multiple_hostgroup
|
||
update_multiple_hostgroup select_multiple_environment update_multiple_environment
|
||
update_multiple_hostgroup
|
||
multiple_destroy submit_multiple_destroy multiple_build
|
||
submit_multiple_build multiple_disable submit_multiple_disable
|
||
multiple_enable submit_multiple_enable multiple_puppetrun
|
||
update_multiple_puppetrun multiple_disassociate update_multiple_disassociate
|
||
multiple_enable submit_multiple_enable
|
||
multiple_disassociate update_multiple_disassociate
|
||
rebuild_config submit_rebuild_config select_multiple_owner update_multiple_owner
|
||
select_multiple_power_state update_multiple_power_state
|
||
select_multiple_puppet_proxy update_multiple_puppet_proxy
|
||
select_multiple_puppet_ca_proxy update_multiple_puppet_ca_proxy)
|
||
select_multiple_power_state update_multiple_power_state)
|
||
|
||
HOST_POWER = {
|
||
:on => { :state => 'on', :title => N_('On') },
|
||
... | ... | |
:na => { :state => 'na', :title => N_('N/A') }
|
||
}.freeze
|
||
|
||
add_smart_proxy_filters PUPPETMASTER_ACTIONS, :features => ['Puppet']
|
||
|
||
before_action :ajax_request, :only => AJAX_REQUESTS + [:get_power_state]
|
||
before_action :find_resource, :only => [:show, :clone, :edit, :update, :destroy, :puppetrun, :review_before_build,
|
||
:setBuild, :cancelBuild, :power, :get_power_state, :overview, :bmc, :vm,
|
||
... | ... | |
before_action :set_host_type, :only => [:update]
|
||
before_action :find_multiple, :only => MULTIPLE_ACTIONS
|
||
before_action :validate_power_action, :only => :update_multiple_power_state
|
||
before_action :validate_multiple_puppet_proxy, :only => :update_multiple_puppet_proxy
|
||
before_action :validate_multiple_puppet_ca_proxy, :only => :update_multiple_puppet_ca_proxy
|
||
helper :hosts, :reports, :interfaces
|
||
|
||
def index(title = nil)
|
||
... | ... | |
redirect_back_or_to hosts_path
|
||
end
|
||
|
||
def select_multiple_environment
|
||
end
|
||
|
||
def update_multiple_environment
|
||
# simple validations
|
||
if (params[:environment].nil?) || (id=params["environment"]["id"]).nil?
|
||
error _('No environment selected!')
|
||
redirect_to(select_multiple_environment_hosts_path)
|
||
return
|
||
end
|
||
|
||
ev = Environment.find_by_id(id)
|
||
|
||
#update the hosts
|
||
@hosts.each do |host|
|
||
host.environment = (id == 'inherit' && host.hostgroup.present?) ? host.hostgroup.environment : ev
|
||
host.save(:validate => false)
|
||
end
|
||
|
||
notice _('Updated hosts: changed environment')
|
||
redirect_back_or_to hosts_path
|
||
end
|
||
|
||
def select_multiple_owner
|
||
end
|
||
|
||
... | ... | |
redirect_back_or_to hosts_path
|
||
end
|
||
|
||
def select_multiple_puppet_proxy
|
||
end
|
||
|
||
def update_multiple_puppet_proxy
|
||
update_multiple_proxy(_('Puppet'), :puppet_proxy=)
|
||
end
|
||
|
||
def select_multiple_puppet_ca_proxy
|
||
end
|
||
|
||
def update_multiple_puppet_ca_proxy
|
||
update_multiple_proxy(_('Puppet CA'), :puppet_ca_proxy=)
|
||
end
|
||
|
||
def multiple_destroy
|
||
end
|
||
|
||
... | ... | |
toggle_hostmode
|
||
end
|
||
|
||
def multiple_puppetrun
|
||
deny_access unless Setting[:puppetrun]
|
||
end
|
||
|
||
def update_multiple_puppetrun
|
||
return deny_access unless Setting[:puppetrun]
|
||
if @hosts.map(&:puppetrun!).uniq == [true]
|
||
notice _("Successfully executed, check reports and/or log files for more details")
|
||
else
|
||
error _("Some or all hosts execution failed, Please check log files for more information")
|
||
end
|
||
redirect_back_or_to hosts_path
|
||
end
|
||
|
||
def multiple_disassociate
|
||
@non_physical_hosts = @hosts.with_compute_resource
|
||
@physical_hosts = @hosts.to_a - @non_physical_hosts.to_a
|
||
... | ... | |
end
|
||
@host.set_hostgroup_defaults true
|
||
@host.set_compute_attributes unless params[:host][:compute_profile_id]
|
||
|
||
@architecture = @host.architecture
|
||
@operatingsystem = @host.operatingsystem
|
||
@environment = @host.environment
|
||
@domain = @host.domain
|
||
@subnet = @host.subnet
|
||
@compute_profile = @host.compute_profile
|
||
@realm = @host.realm
|
||
|
||
set_class_variables(@host)
|
||
render :partial => "form"
|
||
end
|
||
|
||
... | ... | |
@resource_base ||= Host.authorized(current_permission, Host)
|
||
end
|
||
|
||
def action_permission
|
||
case params[:action]
|
||
when 'clone', 'externalNodes', 'overview', 'bmc', 'vm', 'runtime', 'resources', 'templates', 'nics',
|
||
'pxe_config', 'storeconfig_klasses', 'active', 'errors', 'out_of_sync', 'pending', 'disabled',
|
||
'get_power_state'
|
||
:view
|
||
when 'puppetrun', 'multiple_puppetrun', 'update_multiple_puppetrun'
|
||
:puppetrun
|
||
when 'setBuild', 'cancelBuild', 'multiple_build', 'submit_multiple_build', 'review_before_build',
|
||
'rebuild_config', 'submit_rebuild_config'
|
||
:build
|
||
when 'power'
|
||
:power
|
||
when 'ipmi_boot'
|
||
:ipmi_boot
|
||
when 'console'
|
||
:console
|
||
when 'toggle_manage', 'multiple_parameters', 'update_multiple_parameters',
|
||
'select_multiple_hostgroup', 'update_multiple_hostgroup', 'select_multiple_environment',
|
||
'update_multiple_environment', 'multiple_disable', 'submit_multiple_disable',
|
||
'multiple_enable', 'submit_multiple_enable',
|
||
'update_multiple_organization', 'select_multiple_organization',
|
||
'update_multiple_location', 'select_multiple_location',
|
||
'disassociate', 'update_multiple_disassociate', 'multiple_disassociate',
|
||
'select_multiple_owner', 'update_multiple_owner',
|
||
'select_multiple_power_state', 'update_multiple_power_state',
|
||
'select_multiple_puppet_proxy', 'update_multiple_puppet_proxy',
|
||
'select_multiple_puppet_ca_proxy', 'update_multiple_puppet_ca_proxy',
|
||
'random_name'
|
||
:edit
|
||
when 'multiple_destroy', 'submit_multiple_destroy'
|
||
:destroy
|
||
else
|
||
super
|
||
end
|
||
end
|
||
define_action_permission [
|
||
'clone', 'externalNodes', 'overview', 'bmc', 'vm', 'runtime', 'resources', 'templates', 'nics',
|
||
'pxe_config', 'storeconfig_klasses', 'active', 'errors', 'out_of_sync', 'pending', 'disabled', 'get_power_state'], :view
|
||
define_action_permission [
|
||
'setBuild', 'cancelBuild', 'multiple_build', 'submit_multiple_build', 'review_before_build',
|
||
'rebuild_config', 'submit_rebuild_config'], :build
|
||
define_action_permission 'power', :power
|
||
define_action_permission 'ipmi_boot', :ipmi_boot
|
||
define_action_permission 'console', :console
|
||
define_action_permission [
|
||
'toggle_manage', 'multiple_parameters', 'update_multiple_parameters',
|
||
'select_multiple_hostgroup', 'update_multiple_hostgroup',
|
||
'multiple_disable', 'submit_multiple_disable',
|
||
'multiple_enable', 'submit_multiple_enable',
|
||
'update_multiple_organization', 'select_multiple_organization',
|
||
'update_multiple_location', 'select_multiple_location',
|
||
'disassociate', 'update_multiple_disassociate', 'multiple_disassociate',
|
||
'select_multiple_owner', 'update_multiple_owner',
|
||
'select_multiple_power_state', 'update_multiple_power_state', 'random_name'], :edit
|
||
define_action_permission ['multiple_destroy', 'submit_multiple_destroy'], :destroy
|
||
|
||
def refresh_host
|
||
@host = Host::Base.authorized(:view_hosts, Host).find_by_id(params['host_id'])
|
||
... | ... | |
return unless @host
|
||
|
||
taxonomy_scope
|
||
@environment = @host.environment
|
||
@architecture = @host.architecture
|
||
@domain = @host.domain
|
||
@operatingsystem = @host.operatingsystem
|
||
@medium = @host.medium
|
||
if @host.compute_resource_id && params[:host] && params[:host][:compute_attributes]
|
||
@host.compute_attributes = params[:host][:compute_attributes]
|
||
end
|
||
|
||
set_class_variables(@host)
|
||
end
|
||
|
||
def find_multiple
|
||
... | ... | |
raise Foreman::Exception.new(N_("No templates found")) if @templates.empty?
|
||
end
|
||
|
||
def set_class_variables(host)
|
||
run_callbacks :set_class_variables do
|
||
@architecture = host.architecture
|
||
@operatingsystem = host.operatingsystem
|
||
@domain = host.domain
|
||
@subnet = host.subnet
|
||
@compute_profile = host.compute_profile
|
||
@realm = host.realm
|
||
end
|
||
end
|
||
|
||
def host_power_ping(result)
|
||
timeout = 3
|
||
Timeout.timeout(timeout) do
|
test/unit/concerns/action_permission_dsl_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
module ActionPermissionDslTestModule
|
||
class DummyControllerBase
|
||
def action_permission
|
||
:base_controller_permission
|
||
end
|
||
end
|
||
|
||
class DummyController < DummyControllerBase
|
||
include ::Foreman::Controller::ActionPermissionDsl
|
||
|
||
attr_accessor :params
|
||
end
|
||
|
||
class ActionPermissionDslTest < ActiveSupport::TestCase
|
||
setup do
|
||
@storage = {}
|
||
DummyController.stubs(:action_permissions).returns(@storage)
|
||
end
|
||
|
||
test 'it enbales singular initialization' do
|
||
DummyController.define_action_permission :action1, :permission1
|
||
instance = DummyController.new
|
||
instance.params = {:action => :action1}
|
||
|
||
actual = instance.action_permission
|
||
|
||
assert_equal :permission1, actual
|
||
end
|
||
|
||
test 'it enables multiple initialization' do
|
||
DummyController.define_action_permission [:action1, :action2], :permission1
|
||
instance = DummyController.new
|
||
instance.params = {:action => :action1}
|
||
|
||
actual = instance.action_permission
|
||
|
||
assert_equal :permission1, actual
|
||
|
||
instance.params = {:action => :action2}
|
||
|
||
actual = instance.action_permission
|
||
|
||
assert_equal :permission1, actual
|
||
end
|
||
|
||
test 'it enables sequential initializations' do
|
||
DummyController.define_action_permission :action1, :permission1
|
||
DummyController.define_action_permission :action2, :permission1
|
||
instance = DummyController.new
|
||
instance.params = {:action => :action1}
|
||
|
||
actual = instance.action_permission
|
||
|
||
assert_equal :permission1, actual
|
||
|
||
instance.params = {:action => :action2}
|
||
|
||
actual = instance.action_permission
|
||
|
||
assert_equal :permission1, actual
|
||
end
|
||
|
||
test 'it runs the base method if the action was not specified explicitly' do
|
||
DummyController.define_action_permission :action1, :permission1
|
||
instance = DummyController.new
|
||
instance.params = {:action => :other_action}
|
||
|
||
actual = instance.action_permission
|
||
|
||
assert_equal :base_controller_permission, actual
|
||
end
|
||
end
|
||
end
|
Also available in: Unified diff
Fixes #15403 - moved puppet to a concern in hosts UI controller