diff --git a/Gemfile b/Gemfile index 19ceae4ce331..d4a5634a9671 100644 --- a/Gemfile +++ b/Gemfile @@ -4,29 +4,28 @@ require File.expand_path('../lib/regexp_extensions', FOREMAN_GEMFILE) source 'https://rubygems.org' -gem 'rails', '3.2.22' -gem 'rack-cache', '< 1.3.0' +gem 'rails', '4.1.5' gem 'json', '~> 1.5' gem 'rest-client', '~> 1.6.0', :require => 'rest_client' -gem 'audited-activerecord', '3.0.0' +gem 'audited-activerecord', '~> 4.0' gem 'will_paginate', '~> 3.0' gem 'ancestry', '~> 2.0' -gem 'scoped_search', '~> 3.0' +gem 'scoped_search', '>= 3.2.2', '< 4' gem 'ldap_fluff', '>= 0.3.5', '< 1.0' gem 'net-ldap', '>= 0.8.0' -gem 'apipie-rails', '~> 0.2.5' +gem 'apipie-rails', '~> 0.3.4' gem 'rabl', '~> 0.11' gem 'oauth', '~> 0.4' gem 'deep_cloneable', '~> 2.0' gem 'foreigner', '~> 1.4' gem 'validates_lengths_from_database', '~> 0.2' -gem 'friendly_id', '~> 4.0' +gem 'friendly_id', '~> 5.0' gem 'secure_headers', '~> 1.3' gem 'safemode', '~> 1.2' gem 'fast_gettext', '~> 0.8' gem 'gettext_i18n_rails', '~> 1.0' gem 'i18n', '~> 0.6.4' -gem 'rails-i18n', '~> 3.0.0' +gem 'rails-i18n', '~> 4.0.0' gem 'turbolinks', '~> 2.5' gem 'logging', '>= 1.8.0', '< 3.0.0' gem 'fog-core', '1.34.0' @@ -36,6 +35,9 @@ if RUBY_VERSION.start_with? '1.9.' else gem 'net-ssh' end +gem 'activerecord-session_store', '~> 0.1.1' +gem 'rails-observers', '~> 0.1' +gem 'protected_attributes', '~> 1.1.1' Dir["#{File.dirname(FOREMAN_GEMFILE)}/bundler.d/*.rb"].each do |bundle| self.instance_eval(Bundler.read_file(bundle)) diff --git a/app/assets/javascripts/host_checkbox.js b/app/assets/javascripts/host_checkbox.js.erb similarity index 84% rename from app/assets/javascripts/host_checkbox.js rename to app/assets/javascripts/host_checkbox.js.erb index 00ba01c9af27..c1c5a5eb808d 100644 --- a/app/assets/javascripts/host_checkbox.js +++ b/app/assets/javascripts/host_checkbox.js.erb @@ -118,20 +118,21 @@ function submit_modal_form() { function build_modal(element, url) { var url = url + "?" + $.param({host_ids: $.foremanSelectedHosts}); var title = $(element).attr('data-dialog-title'); - $('#confirmation-modal .modal-header h4').text(title); - $('#confirmation-modal .modal-body').empty().append(""); - $('#confirmation-modal').modal(); - $("#confirmation-modal .modal-body").load(url + " #content", - function(response, status, xhr) { - $("#loading").hide(); - $('#submit_multiple').val(''); - var b = $("#confirmation-modal .btn-primary"); - if ($(response).find('#content form select').length > 0) - b.addClass("disabled").attr("disabled", true); - else - b.removeClass("disabled").attr("disabled", false); - }); - return false; + $('#confirmation-modal .modal-header h4').text(title); + $('#confirmation-modal .modal-body').empty() + .append("'"); + $('#confirmation-modal').modal(); + $("#confirmation-modal .modal-body").load(url + " #content", + function(response, status, xhr) { + $("#loading").hide(); + $('#submit_multiple').val(''); + var b = $("#confirmation-modal .btn-primary"); + if ($(response).find('#content form select').length > 0) + b.addClass("disabled").attr("disabled", true); + else + b.removeClass("disabled").attr("disabled", false); + }); + return false; } diff --git a/app/assets/javascripts/topbar.js b/app/assets/javascripts/topbar.js index 4499eb3ad4a0..dc85785638b2 100644 --- a/app/assets/javascripts/topbar.js +++ b/app/assets/javascripts/topbar.js @@ -50,7 +50,7 @@ $(document).on('mouseleave','.loc-submenu', function(){ function mark_active_menu() { var menus = $('.menu_tab_dropdown'), path = window.location.pathname + window.location.search, - link = $("[href='%s'".replace('%s', path)); + link = $("[href='%s']".replace('%s', path)); menus.removeClass('active'); $("[class^='menu_tab_']").removeClass('active'); diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index f49daa103dee..1cbfbaa958bc 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -108,11 +108,11 @@ a.config_group_name { } .editable { - background: url("edit.png") no-repeat scroll 98% 6px transparent; + background: image-url("edit.png") no-repeat scroll 98% 6px transparent; cursor: pointer; padding: 4px 26px 4px 0; &:hover { - background: url("edit-hover.png") no-repeat scroll 98% 6px #F2F2F2; + background: image-url("edit-hover.png") no-repeat scroll 98% 6px #F2F2F2; } } @@ -282,23 +282,23 @@ table { } .sorting { - background: url('sort_both.png') no-repeat center right; + background: image-url('sort_both.png') no-repeat center right; } .sorting_asc { - background: url('sort_asc.png') no-repeat center right; + background: image-url('sort_asc.png') no-repeat center right; } .sorting_desc { - background: url('sort_desc.png') no-repeat center right; + background: image-url('sort_desc.png') no-repeat center right; } .sorting_asc_disabled { - background: url('sort_asc_disabled.png') no-repeat center right; + background: image-url('sort_asc_disabled.png') no-repeat center right; } .sorting_desc_disabled { - background: url('sort_desc_disabled.png') no-repeat center right; + background: image-url('sort_desc_disabled.png') no-repeat center right; } } @@ -340,7 +340,7 @@ table { .spinner-placeholder { width: 16px; height: 16px; - background: url('spinner.gif'); + background: image-url('spinner.gif'); text-indent: 20px; white-space: nowrap; margin: 20% 30% 0 40%; @@ -537,3 +537,7 @@ span.glyphicon.host-status { word-wrap: break-word; /* IE */ word-break: break-all; } + +.ms-container { + background: transparent image-url('switch.png') no-repeat 270px 80px; +} diff --git a/app/assets/stylesheets/charts.scss b/app/assets/stylesheets/charts.scss index bf3877087043..7492a88b1817 100644 --- a/app/assets/stylesheets/charts.scss +++ b/app/assets/stylesheets/charts.scss @@ -122,9 +122,9 @@ } .statistics-pie.small .overlay { - background: url(/assets/pie_overlay.png) no-repeat; + background: image-url('/assets/pie_overlay.png') no-repeat; background-size: cover; - -ms-behavior: url(/assets/background-size.htc); + -ms-behavior: asset-url('/assets/background-size.htc'); z-index: 1; } diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index eaa8fa59e201..5165a6a21566 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -36,7 +36,7 @@ def destroy param :id, :identifier, :required => true def last - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + conditions = { :host_id => Host.authorized(:view_hosts).friendly.find(params[:host_id]).try(:id) } if params[:host_id].present? max_id = resource_scope.where(conditions).maximum(:id) @report = resource_scope.includes(:logs => [:message, :source]).find(max_id) render :show diff --git a/app/controllers/api/v2/config_reports_controller.rb b/app/controllers/api/v2/config_reports_controller.rb index 46e4c8f7508a..1da7141d6737 100644 --- a/app/controllers/api/v2/config_reports_controller.rb +++ b/app/controllers/api/v2/config_reports_controller.rb @@ -54,7 +54,9 @@ def destroy param :id, :identifier, :required => true def last - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + if params[:host_id].present? + conditions = { :host_id => resource_finder(Host.authorized(:view_hosts), params[:host_id]).try(:id) } + end max_id = resource_scope.where(conditions).maximum(:id) @config_report = resource_scope.includes(:logs => [:message, :source]).find(max_id) render :show diff --git a/app/controllers/api/v2/host_classes_controller.rb b/app/controllers/api/v2/host_classes_controller.rb index 28c4b82bcad8..ff8dcdf38a11 100644 --- a/app/controllers/api/v2/host_classes_controller.rb +++ b/app/controllers/api/v2/host_classes_controller.rb @@ -35,8 +35,10 @@ def destroy # overwrite resource_name so it's host and and not host_class, since we want to return @host def find_host not_found and return false if params[:host_id].blank? - @host = Host.find(params[:host_id]) if Host::Managed.respond_to?(:authorized) && - Host::Managed.authorized("view_host", Host::Managed) + if Host::Managed.respond_to?(:authorized) && + Host::Managed.authorized("view_host", Host::Managed) + @host = resource_finder(Host.authorized(:view_hosts), params[:host_id]) + end end end end diff --git a/app/controllers/api/v2/models_controller.rb b/app/controllers/api/v2/models_controller.rb index 9554fe389592..1a288ab6e3b4 100644 --- a/app/controllers/api/v2/models_controller.rb +++ b/app/controllers/api/v2/models_controller.rb @@ -47,6 +47,12 @@ def update def destroy process_response @model.destroy end + + private + + def find_resource + @model = Model.friendly.find(params[:id]) || super + end end end end diff --git a/app/controllers/api/v2/parameters_controller.rb b/app/controllers/api/v2/parameters_controller.rb index 0d3f536396b1..fd0ebae7b489 100644 --- a/app/controllers/api/v2/parameters_controller.rb +++ b/app/controllers/api/v2/parameters_controller.rb @@ -165,8 +165,9 @@ def allowed_nested_id def find_parameter # nested_obj is required, so no need to check here @parameters = nested_obj.send(parameters_method) - @parameter = @parameters.find(params[:id]) - return @parameter if @parameter + @parameter = @parameters.from_param(params[:id]) + @parameter ||= @parameters.friendly.find(params[:id]) + return @parameter if @parameter.present? not_found end end diff --git a/app/controllers/api/v2/reports_controller.rb b/app/controllers/api/v2/reports_controller.rb index b432de0b0fde..ca5006c20cb3 100644 --- a/app/controllers/api/v2/reports_controller.rb +++ b/app/controllers/api/v2/reports_controller.rb @@ -54,7 +54,7 @@ def destroy param :id, :identifier, :required => true def last - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + conditions = { :host_id => resource_finder(Host.authorized(:view_hosts), params[:host_id]).try(:id) } if params[:host_id].present? max_id = resource_scope.where(conditions).maximum(:id) @report = resource_scope.includes(:logs => [:message, :source]).find(max_id) render :show diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 383587134e9a..fddc6e673c94 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -193,7 +193,7 @@ def remote_user_provided? end def display_layout? - return nil if two_pane? + return false if two_pane? "application" end diff --git a/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb b/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb index 009eef9d15ff..5e76e13f01e5 100644 --- a/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb +++ b/app/controllers/concerns/api/v2/lookup_keys_common_controller.rb @@ -19,22 +19,6 @@ module Api::V2::LookupKeysCommonController before_filter :return_if_smart_mismatch, :only => [:show, :update, :destroy] end - def puppetclass_id? - params.keys.include?('puppetclass_id') - end - - def environment_id? - params.keys.include?('environment_id') - end - - def host_id? - params.keys.include?('host_id') - end - - def hostgroup_id? - params.keys.include?('hostgroup_id') - end - def smart_variable_id? params.keys.include?('smart_variable_id') || controller_name.match(/smart_variables/) end @@ -43,28 +27,22 @@ def smart_class_parameter_id? params.keys.include?('smart_class_parameter_id') || controller_name.match(/smart_class_parameters/) end - def find_puppetclass - @puppetclass = Puppetclass.authorized(:view_puppetclasses).find(params['puppetclass_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Puppet class with id '%{id}' was not found") % { :id => params['puppetclass_id'] }) } }) - end + [Puppetclass, Environment, Host::Base, Hostgroup].each do |model| + model_string = model.to_s.split('::').first.downcase - def find_environment - @environment = Environment.authorized(:view_environments).find(params['environment_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Environment with id '%{id}' was not found") % { :id => params['environment_id'] }) } }) - end - - def find_host - @host = Host::Base.authorized(:view_hosts).find(params['host_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Host with id '%{id}' was not found") % { :id => params['host_id'] }) } }) - end + define_method("#{model_string}_id?") do + params.keys.include?("#{model_string}_id") + end - def find_hostgroup - @hostgroup = Hostgroup.authorized(:view_hostgroups).find(params['hostgroup_id']) - rescue ActiveRecord::RecordNotFound - not_found({ :error => { :message => (_("Hostgroup with id '%{id}' was not found") % { :id => params['hostgroup_id'] }) } }) + define_method("find_#{model_string}") do + scope = model.authorized(:"view_#{model_string.pluralize}") + begin + instance_variable_set("@#{model_string}", + resource_finder(scope, params["#{model_string}_id"])) + rescue ActiveRecord::RecordNotFound + model_not_found(model_string) + end + end end def find_smart_variable @@ -144,4 +122,13 @@ def return_if_smart_mismatch not_found "#{obj} not found by id '#{id}'" end end + + private + + def model_not_found(model) + error_message = ( + _("%{model} with id '%{id}' was not found") % + { :id => params["#{model}_id"], :model => model.capitalize } ) + not_found(:error => { :message => error_message } ) + end end diff --git a/app/controllers/concerns/find_common.rb b/app/controllers/concerns/find_common.rb index 5d8a5a30edd9..a037251e7627 100644 --- a/app/controllers/concerns/find_common.rb +++ b/app/controllers/concerns/find_common.rb @@ -1,12 +1,18 @@ -# this mixin is used by both ApplicationController and Api::BaseController -# searches for an object based on its id, name, label, etc and assign it to an instance variable +# This mixin is used by both ApplicationController and Api::BaseController +# Searches for an object based on its id, name, label, etc and assign it to an instance variable # friendly_id performs the logic if params[:id] is 'id' or 'id-name' or 'name' module FindCommon - # example: @host = Host.find(params[:id]) def find_resource - not_found and return if params[:id].blank? - instance_variable_set("@#{resource_name}", resource_scope.find(params[:id])) + instance_variable_set("@#{resource_name}", + resource_finder(resource_scope, params[:id])) + end + + def resource_finder(scope, id) + raise ActiveRecord::RecordNotFound if scope.empty? + result = scope.from_param(id) if scope.respond_to?(:from_param) + result ||= scope.friendly.find(id) if scope.respond_to?(:friendly) + result || scope.find(id) end def resource_name(resource = controller_name) diff --git a/app/controllers/config_reports_controller.rb b/app/controllers/config_reports_controller.rb index 436cf0b9a850..8b404ca971d8 100644 --- a/app/controllers/config_reports_controller.rb +++ b/app/controllers/config_reports_controller.rb @@ -10,7 +10,7 @@ def index def show # are we searching for the last report? if params[:id] == "last" - conditions = { :host_id => Host.authorized(:view_hosts).find(params[:host_id]).try(:id) } if params[:host_id].present? + conditions = { :host_id => resource_finder(Host.authorized(:view_hosts), params[:host_id]).try(:id) } if params[:host_id].present? params[:id] = resource_base.where(conditions).maximum(:id) end diff --git a/app/controllers/hosts_controller.rb b/app/controllers/hosts_controller.rb index aeca21fc36ea..e4e1f07dcca0 100644 --- a/app/controllers/hosts_controller.rb +++ b/app/controllers/hosts_controller.rb @@ -169,7 +169,7 @@ def puppetclass_parameters def externalNodes certname = params[:name] @host ||= resource_base.find_by_certname certname - @host ||= resource_base.find certname + @host ||= resource_base.friendly.find certname not_found and return unless @host begin @@ -352,7 +352,7 @@ def update_multiple_parameters skipped = [] params[:name].each do |name, value| next if value.empty? - if (host_param = host.host_parameters.find(name)) + if (host_param = host.host_parameters.friendly.find(name)) counter += 1 if host_param.update_attribute(:value, value) else skipped << name @@ -698,7 +698,7 @@ def taxonomy_scope # overwrite application_controller def find_resource not_found and return false if (id = params[:id]).blank? - @host = resource_base.find(id) + @host = resource_base.friendly.find(id) @host ||= resource_base.find_by_mac params[:host][:mac] if params[:host] && params[:host][:mac] not_found and return(false) unless @host diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index ef4133685ef5..57d7bd6686ed 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -13,7 +13,7 @@ def index end def update - @setting = Setting.find(params[:id]) + @setting = Setting.friendly.find(params[:id]) if @setting.parse_string_value(params[:setting][:value]) && @setting.save render :json => @setting else diff --git a/app/controllers/unattended_controller.rb b/app/controllers/unattended_controller.rb index 0678436c17f2..4d14e53198c1 100644 --- a/app/controllers/unattended_controller.rb +++ b/app/controllers/unattended_controller.rb @@ -44,8 +44,8 @@ def built def template return head(:not_found) unless (params.has_key?("id") and params.has_key?(:hostgroup)) - template = ProvisioningTemplate.find(params['id']) - @host = Hostgroup.find(params['hostgroup']) + template = ProvisioningTemplate.find_by_name(params['id']) + @host = Hostgroup.find_by_name(params['hostgroup']) return head(:not_found) unless template and @host @@ -107,7 +107,7 @@ def get_host_details def find_host_by_spoof host = Nic::Base.primary.find_by_ip(params.delete('spoof')).try(:host) if params['spoof'].present? - host ||= Host.find(params.delete('hostname')) if params['hostname'].present? + host ||= Host.find_by_name(params.delete('hostname')) if params['hostname'].present? @spoof = host.present? host end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b29f756a73d2..887d3fb1d8f6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -32,6 +32,14 @@ def link_to(*args, &block) end end + def link_to_function(name, function, html_options = {}) + onclick_tag = "#{html_options[:onclick]}; " if html_options[:onclick] + onclick = "#{onclick_tag}#{function}; return false;" + href = html_options[:href] || '#' + + content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick)) + end + protected def contract(model) diff --git a/app/models/bookmark.rb b/app/models/bookmark.rb index ffed9d221d6c..1cccd037abde 100644 --- a/app/models/bookmark.rb +++ b/app/models/bookmark.rb @@ -7,7 +7,7 @@ class Bookmark < ActiveRecord::Base validates_lengths_from_database belongs_to :owner, :polymorphic => true - attr_accessible :name, :controller, :query, :public + attr_accessible :name, :query, :public, :controller audited :allow_mass_assignment => true validates :name, :uniqueness => {:scope => :controller}, :unless => Proc.new{|b| Bookmark.my_bookmarks.where(:name => b.name).empty?} diff --git a/app/models/compute_profile.rb b/app/models/compute_profile.rb index d30cc211f1ee..20864e463d8d 100644 --- a/app/models/compute_profile.rb +++ b/app/models/compute_profile.rb @@ -6,6 +6,7 @@ class ComputeProfile < ActiveRecord::Base validates_lengths_from_database attr_accessible :name + audited has_associated_audits diff --git a/app/models/concerns/audit_extensions.rb b/app/models/concerns/audit_extensions.rb index a1ec3226f7ab..aef24f0a0232 100644 --- a/app/models/concerns/audit_extensions.rb +++ b/app/models/concerns/audit_extensions.rb @@ -5,7 +5,8 @@ module AuditExtensions included do belongs_to :user, :class_name => 'User' belongs_to :search_users, :class_name => 'User', :foreign_key => :user_id - belongs_to :search_hosts, :class_name => 'Host', :foreign_key => :auditable_id, :conditions => { :audits => { :auditable_type => 'Host' } } + belongs_to :search_hosts, -> { where(:audits => { :auditable_type => 'Host' }) }, + :class_name => 'Host', :foreign_key => :auditable_id belongs_to :search_hostgroups, :class_name => 'Hostgroup', :foreign_key => :auditable_id belongs_to :search_parameters, :class_name => 'Parameter', :foreign_key => :auditable_id belongs_to :search_templates, :class_name => 'ProvisioningTemplate', :foreign_key => :auditable_id diff --git a/app/models/concerns/has_many_common.rb b/app/models/concerns/has_many_common.rb index 9b013d829cb3..2fc55e62907e 100644 --- a/app/models/concerns/has_many_common.rb +++ b/app/models/concerns/has_many_common.rb @@ -41,8 +41,9 @@ class << self; self end end #### has_many #### - def has_many(association, options = {}) - has_many_names_for(association, options) + def has_many(*args) + options = args.last.is_a?(Hash) ? args.last : {} + has_many_names_for(args.first, options) super end @@ -69,8 +70,9 @@ def has_many_names_for(association, options) end #### belongs_to #### - def belongs_to(association, options = {}) - belongs_to_name_for(association, options) + def belongs_to(*args) + options = args.last.is_a?(Hash) ? args.last : {} + belongs_to_name_for(args.first, options) super end diff --git a/app/models/concerns/host_common.rb b/app/models/concerns/host_common.rb index 69d9b606ec5a..c7fadfeb5851 100644 --- a/app/models/concerns/host_common.rb +++ b/app/models/concerns/host_common.rb @@ -209,7 +209,7 @@ def individual_puppetclasses end def available_puppetclasses - return Puppetclass.where(nil) if environment_id.blank? + return Puppetclass.where(nil) if environment.blank? environment.puppetclasses - parent_classes end diff --git a/app/models/concerns/host_params.rb b/app/models/concerns/host_params.rb index ff3f685bea2d..37c0afedab40 100644 --- a/app/models/concerns/host_params.rb +++ b/app/models/concerns/host_params.rb @@ -7,6 +7,7 @@ module HostParams accepts_nested_attributes_for :host_parameters, :allow_destroy => true include ParameterValidators attr_reader :cached_host_params + attr_accessible :host_parameters_attributes def params host_params.update(lookup_keys_params) @@ -58,7 +59,7 @@ def host_inherited_params_objects def host_params_objects # Host parameters should always be first for the uniq order - (host_parameters + host_inherited_params_objects.reverse!).uniq {|param| param.name} + (host_parameters + host_inherited_params_objects.to_a.reverse!).uniq {|param| param.name} end end end diff --git a/app/models/concerns/parameterizable.rb b/app/models/concerns/parameterizable.rb index 4a0c63e36487..0fb27066e476 100644 --- a/app/models/concerns/parameterizable.rb +++ b/app/models/concerns/parameterizable.rb @@ -12,7 +12,7 @@ def to_param end def self.from_param(id) - self.find(id.to_i) + self.find_by_id(id.to_i) end end end @@ -27,7 +27,7 @@ def to_param end def self.from_param(id_name) - self.find(id_name.to_i) + self.find_by_id(id_name.to_i) end end end diff --git a/app/models/concerns/taxonomix.rb b/app/models/concerns/taxonomix.rb index 45019c254cd2..75f116a14c67 100644 --- a/app/models/concerns/taxonomix.rb +++ b/app/models/concerns/taxonomix.rb @@ -3,12 +3,14 @@ module Taxonomix include DirtyAssociations included do - taxonomy_join_table = "taxable_taxonomies" - has_many taxonomy_join_table, :dependent => :destroy, :as => :taxable - has_many :locations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Location'", :validate => false - has_many :organizations, :through => taxonomy_join_table, :source => :taxonomy, - :conditions => "taxonomies.type='Organization'", :validate => false + taxonomy_join_table = :taxable_taxonomies + has_many taxonomy_join_table.to_sym, :dependent => :destroy, :as => :taxable + has_many :locations, -> { where(:type => 'Location') }, + :through => taxonomy_join_table, :source => :taxonomy, + :validate => false + has_many :organizations, -> { where(:type => 'Organization') }, + :through => taxonomy_join_table, :source => :taxonomy, + :validate => false after_initialize :set_current_taxonomy scoped_search :in => :locations, :on => :name, :rename => :location, :complete_value => true diff --git a/app/models/config_group_class.rb b/app/models/config_group_class.rb index 904d58fd4a4f..2e22eb5f9b37 100644 --- a/app/models/config_group_class.rb +++ b/app/models/config_group_class.rb @@ -9,7 +9,7 @@ class ConfigGroupClass < ActiveRecord::Base belongs_to :puppetclass belongs_to :config_group, :counter_cache => true - validates :puppetclass_id, :presence => true - validates :config_group_id, :presence => true, - :uniqueness => {:scope => :puppetclass_id} + validates :puppetclass, :presence => true + validates :config_group, :presence => true, + :uniqueness => {:scope => :puppetclass} end diff --git a/app/models/domain.rb b/app/models/domain.rb index be367e0c178c..2ea9fa2cb0ef 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -21,7 +21,7 @@ class Domain < ActiveRecord::Base has_many :domain_parameters, :dependent => :destroy, :foreign_key => :reference_id, :inverse_of => :domain has_many :parameters, :dependent => :destroy, :foreign_key => :reference_id, :class_name => "DomainParameter" has_many :interfaces, :class_name => 'Nic::Base' - has_many :primary_interfaces, :class_name => 'Nic::Base', :conditions => { :primary => true } + has_many :primary_interfaces, -> { where(:primary => true) }, :class_name => 'Nic::Base' has_many :hosts, :through => :interfaces has_many :primary_hosts, :through => :primary_interfaces, :source => :host diff --git a/app/models/environment.rb b/app/models/environment.rb index fdf3007b88af..045abe5c05a7 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -11,12 +11,12 @@ class Environment < ActiveRecord::Base before_destroy EnsureNotUsedBy.new(:hosts, :hostgroups) has_many :environment_classes, :dependent => :destroy - has_many :puppetclasses, :through => :environment_classes, :uniq => true + has_many :puppetclasses, -> { uniq }, :through => :environment_classes has_many_hosts has_many :hostgroups - has_many :trends, :as => :trendable, :class_name => "ForemanTrend" validates :name, :uniqueness => true, :presence => true, :alphanumeric => true + has_many :trends, :as => :trendable, :class_name => "ForemanTrend" has_many :template_combinations, :dependent => :destroy has_many :provisioning_templates, :through => :template_combinations diff --git a/app/models/host/base.rb b/app/models/host/base.rb index 41d3c1a2d8df..9b41c504f9fd 100644 --- a/app/models/host/base.rb +++ b/app/models/host/base.rb @@ -39,12 +39,10 @@ class Base < ActiveRecord::Base belongs_to :model, :counter_cache => :hosts_count has_many :fact_values, :dependent => :destroy, :foreign_key => :host_id has_many :fact_names, :through => :fact_values - has_many :interfaces, :dependent => :destroy, :inverse_of => :host, :class_name => 'Nic::Base', - :foreign_key => :host_id, :order => 'identifier' - has_one :primary_interface, :class_name => 'Nic::Base', :foreign_key => 'host_id', - :conditions => { :primary => true } - has_one :provision_interface, :class_name => 'Nic::Base', :foreign_key => 'host_id', - :conditions => { :provision => true } + has_many :interfaces, -> { order(:identifier) }, :dependent => :destroy, :inverse_of => :host, :class_name => 'Nic::Base', + :foreign_key => :host_id + has_one :primary_interface, -> { where(:primary => true) }, :class_name => 'Nic::Base', :foreign_key => 'host_id' + has_one :provision_interface, -> { where(:provision => true) }, :class_name => 'Nic::Base', :foreign_key => 'host_id' has_one :domain, :through => :primary_interface has_one :subnet, :through => :primary_interface accepts_nested_attributes_for :interfaces, :allow_destroy => true diff --git a/app/models/host/managed.rb b/app/models/host/managed.rb index 4e7969496ba6..d16c36e844be 100644 --- a/app/models/host/managed.rb +++ b/app/models/host/managed.rb @@ -12,10 +12,8 @@ class Host::Managed < Host::Base belongs_to :owner, :polymorphic => true belongs_to :compute_resource belongs_to :image - has_many :host_statuses, :class_name => 'HostStatus::Status', :foreign_key => 'host_id', :inverse_of => :host, - :dependent => :destroy + has_many :host_statuses, :class_name => 'HostStatus::Status', :foreign_key => 'host_id', :inverse_of => :host, :dependent => :destroy has_one :configuration_status_object, :class_name => 'HostStatus::ConfigurationStatus', :foreign_key => 'host_id' - has_one :token, :foreign_key => :host_id, :dependent => :destroy before_destroy :remove_reports @@ -155,7 +153,8 @@ class Jail < ::Safemode::Jail audited :except => [:last_report, :puppet_status, :last_compile, :lookup_value_matcher], :allow_mass_assignment => true has_associated_audits #redefine audits relation because of the type change (by default the relation will look for auditable_type = 'Host::Managed') - has_many :audits, :foreign_key => :auditable_id, :class_name => Audited.audit_class.name, :conditions => { :auditable_type => 'Host' } + has_many :audits, -> { where(:auditable_type => 'Host') }, :foreign_key => :auditable_id, + :class_name => Audited.audit_class.name # some shortcuts alias_attribute :os, :operatingsystem @@ -589,7 +588,7 @@ def apply_inherited_attributes(attributes, initialized = true) new_hostgroup = self.hostgroup if initialized unless [new_hostgroup.try(:id), new_hostgroup.try(:friendly_id)].include? new_hostgroup_id - new_hostgroup = Hostgroup.find(new_hostgroup_id) + new_hostgroup = Hostgroup.friendly.find(new_hostgroup_id) end return attributes unless new_hostgroup @@ -814,11 +813,11 @@ def available_template_kinds(provisioning = nil) cr = ComputeResource.find_by_id(self.compute_resource_id) images = cr.try(:images) if images.blank? - [TemplateKind.find('finish')] + [TemplateKind.friendly.find('finish')] else uuid = self.compute_attributes[cr.image_param_name] image_kind = images.find_by_uuid(uuid).try(:user_data) ? 'user_data' : 'finish' - [TemplateKind.find(image_kind)] + [TemplateKind.friendly.find(image_kind)] end else TemplateKind.all diff --git a/app/models/host_class.rb b/app/models/host_class.rb index e1d078b94c25..e6f8953dcf6c 100644 --- a/app/models/host_class.rb +++ b/app/models/host_class.rb @@ -7,7 +7,6 @@ class HostClass < ActiveRecord::Base belongs_to_host belongs_to :puppetclass - validates :host, :presence => true validates :puppetclass_id, :presence => true, :uniqueness => {:scope => :host_id} def name diff --git a/app/models/hostgroup_class.rb b/app/models/hostgroup_class.rb index 26efa1074b53..ca1203a5f7d6 100644 --- a/app/models/hostgroup_class.rb +++ b/app/models/hostgroup_class.rb @@ -8,7 +8,6 @@ class HostgroupClass < ActiveRecord::Base belongs_to :puppetclass, :counter_cache => :hostgroups_count attr_accessible :hostgroup_id, :hostgroup, :puppetclass_id, :puppetclass - validates :hostgroup, :presence => true validates :puppetclass_id, :presence => true, :uniqueness => {:scope => :hostgroup_id} diff --git a/app/models/lookup_keys/puppetclass_lookup_key.rb b/app/models/lookup_keys/puppetclass_lookup_key.rb index ffb1f8ead157..6cfd122e8a46 100644 --- a/app/models/lookup_keys/puppetclass_lookup_key.rb +++ b/app/models/lookup_keys/puppetclass_lookup_key.rb @@ -1,6 +1,6 @@ class PuppetclassLookupKey < LookupKey has_many :environment_classes, :dependent => :destroy - has_many :environments, :through => :environment_classes, :uniq => true + has_many :environments, -> { uniq }, :through => :environment_classes has_many :param_classes, :through => :environment_classes, :source => :puppetclass scoped_search :in => :param_classes, :on => :name, :rename => :puppetclass, :complete_value => true diff --git a/app/models/operatingsystem.rb b/app/models/operatingsystem.rb index 3678045511b3..382521033e5c 100644 --- a/app/models/operatingsystem.rb +++ b/app/models/operatingsystem.rb @@ -34,6 +34,7 @@ class Operatingsystem < ActiveRecord::Base accepts_nested_attributes_for :os_parameters, :allow_destroy => true include ParameterValidators has_many :trends, :as => :trendable, :class_name => "ForemanTrend" + attr_name :to_label validates :minor, :numericality => {:greater_than_or_equal_to => 0}, :allow_nil => true, :allow_blank => true validates :name, :presence => true, :no_whitespace => true, diff --git a/app/models/puppetclass.rb b/app/models/puppetclass.rb index cc4fbe0d1869..7a5f9cc5fa56 100644 --- a/app/models/puppetclass.rb +++ b/app/models/puppetclass.rb @@ -8,7 +8,7 @@ class Puppetclass < ActiveRecord::Base validates_lengths_from_database before_destroy EnsureNotUsedBy.new(:hosts, :hostgroups) has_many :environment_classes, :dependent => :destroy - has_many :environments, :through => :environment_classes, :uniq => true + has_many :environments, -> { uniq }, :through => :environment_classes has_and_belongs_to_many :operatingsystems has_many :hostgroup_classes has_many :hostgroups, :through => :hostgroup_classes, :dependent => :destroy @@ -19,8 +19,8 @@ class Puppetclass < ActiveRecord::Base has_many :lookup_keys, :inverse_of => :puppetclass, :dependent => :destroy, :class_name => 'VariableLookupKey' accepts_nested_attributes_for :lookup_keys, :reject_if => ->(a) { a[:key].blank? }, :allow_destroy => true # param classes - has_many :class_params, :through => :environment_classes, :uniq => true, - :source => :puppetclass_lookup_key, :conditions => 'environment_classes.puppetclass_lookup_key_id is NOT NULL' + has_many :class_params, -> { where('environment_classes.puppetclass_lookup_key_id is NOT NULL').uniq }, + :through => :environment_classes, :source => :puppetclass_lookup_key accepts_nested_attributes_for :class_params, :reject_if => ->(a) { a[:key].blank? }, :allow_destroy => true validates :name, :uniqueness => true, :presence => true, :no_whitespace => true @@ -202,7 +202,7 @@ def self.prepare_rdoc(root) def self.search_by_host(key, operator, value) conditions = sanitize_sql_for_conditions(["hosts.name #{operator} ?", value_to_sql(operator, value)]) - direct = Puppetclass.joins(:hosts).where(conditions).uniq.pluck('puppetclasses.id') + direct = Puppetclass.joins(:hosts).where(conditions).pluck('puppetclasses.id').uniq hostgroup = Hostgroup.joins(:hosts).where(conditions).first indirect = hostgroup.blank? ? [] : HostgroupClass.where(:hostgroup_id => hostgroup.path_ids).uniq.pluck('puppetclass_id') return { :conditions => "1=0" } if direct.blank? && indirect.blank? diff --git a/app/models/report.rb b/app/models/report.rb index 806fe34a073c..9d5b7484b344 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -31,7 +31,7 @@ class Report < ActiveRecord::Base # returns reports for hosts in the User's filter set scope :my_reports, lambda { if !User.current.admin? || Organization.expand(Organization.current).present? || Location.expand(Location.current).present? - joins_authorized(Host, :view_hosts, :where => Host.taxonomy_conditions) + joins_authorized(Host, :view_hosts) end } diff --git a/app/models/subnet.rb b/app/models/subnet.rb index 735ba11cedd8..9b5d709e0160 100644 --- a/app/models/subnet.rb +++ b/app/models/subnet.rb @@ -23,7 +23,7 @@ class Subnet < ActiveRecord::Base has_many :subnet_domains, :dependent => :destroy has_many :domains, :through => :subnet_domains has_many :interfaces, :class_name => 'Nic::Base' - has_many :primary_interfaces, :class_name => 'Nic::Base', :conditions => { :primary => true } + has_many :primary_interfaces, -> { where(:primary => true) }, :class_name => 'Nic::Base' has_many :hosts, :through => :interfaces has_many :primary_hosts, :through => :primary_interfaces, :source => :host validates :network, :mask, :name, :presence => true diff --git a/app/models/user.rb b/app/models/user.rb index 29e2616d055e..ebc5af10c90b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,10 +25,10 @@ class User < ActiveRecord::Base has_many :auditable_changes, :class_name => '::Audit', :as => :user has_many :direct_hosts, :class_name => 'Host', :as => :owner has_many :usergroup_member, :dependent => :destroy, :as => :member - has_many :user_roles, :dependent => :destroy, :foreign_key => 'owner_id', :conditions => {:owner_type => self.to_s} + has_many :user_roles, -> { where(:owner_type => 'User') }, :dependent => :destroy, :foreign_key => 'owner_id' has_many :cached_user_roles, :dependent => :destroy has_many :cached_usergroups, :through => :cached_usergroup_members, :source => :usergroup - has_many :cached_roles, :through => :cached_user_roles, :source => :role, :uniq => true + has_many :cached_roles, -> { uniq }, :through => :cached_user_roles, :source => :role has_many :usergroups, :through => :usergroup_member, :dependent => :destroy has_many :roles, :through => :user_roles, :dependent => :destroy has_many :filters, :through => :cached_roles @@ -393,6 +393,7 @@ def self.random_password(size = 16) end def expire_topbar_cache(sweeper) + return if sweeper.controller.nil? sweeper.expire_fragment(TopbarSweeper.fragment_name(id)) end diff --git a/app/models/user_mail_notification.rb b/app/models/user_mail_notification.rb index b3869fb43d19..041b2122e34c 100644 --- a/app/models/user_mail_notification.rb +++ b/app/models/user_mail_notification.rb @@ -4,7 +4,7 @@ class UserMailNotification < ActiveRecord::Base belongs_to :user belongs_to :mail_notification - validates :user_id, :presence => true + validates :user, :presence => true validates :mail_notification, :presence => true scope :daily, -> { where(:interval => 'Daily') } diff --git a/app/models/user_role.rb b/app/models/user_role.rb index 5478a528c40d..b49180c46ebd 100644 --- a/app/models/user_role.rb +++ b/app/models/user_role.rb @@ -59,7 +59,7 @@ def cache_user_roles! end def build_user_role_cache - [ self.cached_user_roles.build(:user => owner, :role => role) ] + [ self.cached_user_roles.build(:user_id => owner.id, :role_id => role.id) ] end def build_user_group_role_cache(owner) diff --git a/app/models/usergroup.rb b/app/models/usergroup.rb index 1570670d78ba..c255fd15f203 100644 --- a/app/models/usergroup.rb +++ b/app/models/usergroup.rb @@ -11,7 +11,7 @@ class Usergroup < ActiveRecord::Base validates_lengths_from_database before_destroy EnsureNotUsedBy.new(:hosts), :ensure_last_admin_group_is_not_deleted - has_many :user_roles, :dependent => :destroy, :foreign_key => 'owner_id', :conditions => {:owner_type => self.to_s} + has_many :user_roles, -> { where(:owner_type => 'Usergroup') }, :dependent => :destroy, :foreign_key => 'owner_id' has_many :roles, :through => :user_roles, :dependent => :destroy has_many :usergroup_members, :dependent => :destroy @@ -19,12 +19,14 @@ class Usergroup < ActiveRecord::Base has_many :usergroups, :through => :usergroup_members, :source => :member, :source_type => 'Usergroup', :dependent => :destroy has_many :external_usergroups, :dependent => :destroy, :inverse_of => :usergroup - has_many :cached_usergroup_members - has_many :usergroup_parents, :dependent => :destroy, :foreign_key => 'member_id', - :conditions => "member_type = 'Usergroup'", :class_name => 'UsergroupMember' + has_many :cached_usergroups, :through => :cached_usergroup_members, :source => :usergroup + has_many :cached_usergroup_members, :foreign_key => 'usergroup_id' + has_many :usergroup_parents, -> { where("member_type = 'Usergroup'") }, :dependent => :destroy, + :foreign_key => 'member_id', :class_name => 'UsergroupMember' has_many :parents, :through => :usergroup_parents, :source => :usergroup, :dependent => :destroy has_many_hosts :as => :owner + validates :name, :uniqueness => true, :presence => true # The text item to see in a select dropdown menu diff --git a/app/models/usergroup_member.rb b/app/models/usergroup_member.rb index e27c25c99dd5..781bf438f35d 100644 --- a/app/models/usergroup_member.rb +++ b/app/models/usergroup_member.rb @@ -100,7 +100,7 @@ def find_all_user_roles end def find_all_user_roles_for(usergroup) - usergroup.user_roles + usergroup.parents.map { |g| find_all_user_roles_for(g) } + (UserRole.where(:owner => usergroup )+ usergroup.parents.map { |g| find_all_user_roles_for(g) }).flatten end def find_all_usergroups diff --git a/app/services/foreman/plugin.rb b/app/services/foreman/plugin.rb index 0899b1fc33fe..853a57b45158 100644 --- a/app/services/foreman/plugin.rb +++ b/app/services/foreman/plugin.rb @@ -176,6 +176,9 @@ def delete_menu_item(menu, item) end def tests_to_skip(hash) + Rails.logger.warn "Minitest 5 deprecated the runner API and plugin tests \ +can't be skipped right now. Future versions of Foreman might bring back this \ +feature" # Format is { "testclass" => [ "skip1", "skip2" ] } hash.each do |testclass,tests| if self.class.tests_to_skip[testclass].nil? @@ -219,8 +222,12 @@ def role(name, permissions) end def pending_migrations - migrations = ActiveRecord::Migrator.new(:up, ActiveRecord::Migrator.migrations_paths).pending_migrations - migrations.size > 0 + migration_paths = ActiveRecord::Migrator.migrations( + ActiveRecord::Migrator.migrations_paths) + pending_migrations = ActiveRecord::Migrator.new(:up, migration_paths). + pending_migrations + + pending_migrations.size > 0 end # List of helper methods allowed for templates in safe mode diff --git a/app/services/tax_host.rb b/app/services/tax_host.rb index 010b40d03726..11c8a1ec17f7 100644 --- a/app/services/tax_host.rb +++ b/app/services/tax_host.rb @@ -154,8 +154,9 @@ def non_inherited_ids(v1 = self.selected_ids, v2 = self.inherited_ids) # populate used_ids for 3 non-standard_id's def user_ids(hosts = self.hosts) - #TODO: when migrating to rails 3.1+ switch to inner select on users. - User.unscoped.joins(:direct_hosts).where({ :hosts => { :id => hosts }, :users => { :admin => false } }).pluck('DISTINCT users.id') + User.unscoped.except_admin. + eager_load(:direct_hosts).where(:hosts => { :id => hosts.map(&:id) }). + pluck('DISTINCT users.id') end def provisioning_template_ids(hosts = self.hosts) diff --git a/app/views/api/v2/interfaces/base.json.rabl b/app/views/api/v2/interfaces/base.json.rabl index 43dcaf324f2c..2181267775cf 100644 --- a/app/views/api/v2/interfaces/base.json.rabl +++ b/app/views/api/v2/interfaces/base.json.rabl @@ -2,5 +2,6 @@ object @interface attributes :id, :name, :ip, :mac, :identifier, :primary, :provision node :type do |i| + next if i.is_a? Symbol i.class.humanized_name.downcase end diff --git a/app/views/home/_topbar.html.erb b/app/views/home/_topbar.html.erb index 416e39876889..51df69aa9809 100644 --- a/app/views/home/_topbar.html.erb +++ b/app/views/home/_topbar.html.erb @@ -33,7 +33,7 @@