Project

General

Profile

Feature #366 ยป 366.patch

Ohad Levy, 11/05/2010 06:17 PM

View differences:

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery # See ActionController::RequestForgeryProtection for details
rescue_from ActionController::RoutingError, :with => :no_puppetclass_documentation_handler
# standard layout to all controllers
layout 'standard'
......
before_filter :require_ssl, :require_login
before_filter :load_tabs, :manage_tabs, :unless => :request_json?
before_filter :welcome, :detect_notices, :only => :index, :unless => :request_json?
before_filter :authorize, :except => :login
# Authorize the user for the requested action
def authorize(ctrl = params[:controller], action = params[:action])
return true if request.xhr?
allowed = User.current.allowed_to?({:controller => ctrl, :action => action})
allowed ? true : deny_access
end
def deny_access
User.current.logged? ? render_403 : require_login
end
protected
......
# Force a user to login if authentication is enabled
# Sets @user to the logged in user, or to admin if logins are not used
# Sets User.current to the logged in user, or to admin if logins are not used
def require_login
unless session[:user] and @user = User.find(session[:user])
unless session[:user] and User.current = User.find(session[:user])
# User is not found or first login
if SETTINGS[:login] and SETTINGS[:login] == true
# authentication is enabled
if request_json?
# JSON requests (REST API calls) use basic http authenitcation and should not use/store cookies
@user = authenticate_or_request_with_http_basic { |u, p| User.try_to_login(u, p) }
return !@user.nil?
User.current = authenticate_or_request_with_http_basic { |u, p| User.try_to_login(u, p) }
return !User.current.nil?
end
session[:original_uri] = request.request_uri # keep the old request uri that we can redirect later on
redirect_to login_users_path and return
else
# We assume we always have a user logged in, if authentication is disabled, the user is the build-in admin account.
unless @user = User.find_by_login("admin")
unless User.current = User.find_by_login("admin")
flash[:foreman_error] = "Unable to find internal system admin account - Recreating . . ."
@user = User.create_admin
User.current = User.current = User.create_admin
end
session[:user] = @user.id unless request_json?
session[:user] = User.current.id unless request_json?
end
end
end
def current_user
@user
User.current
end
def invalid_request
......
session[:last_controller] = controller_name
self.active_tab = "" if @controller_changed
return if params[:tab_name].empty? or params[:action] != "index"
return true if params[:tab_name].empty? or params[:action] != "index"
if params[:tab_name] == "Reset"
if params[:tab_name] == "Reset"
self.active_tab = ""
elsif params[:remove_me] and @tabs.has_key? params[:tab_name]
@tabs.delete params[:tab_name]
......
end
end
def require_admin
unless User.current.admin?
render_403
return false
end
true
end
def render_403
respond_to do |format|
format.html { render :template => "common/403", :layout => (request.xhr? ? false : 'standard'), :status => 403 }
format.atom { head 403 }
format.yaml { head 403 }
format.yml { head 403 }
format.xml { head 403 }
format.json { head 403 }
end
return false
end
# this has to be in the application controller, as the new request (for puppetdoc) url is not controller specific.
def no_puppetclass_documentation_handler(exception)
if exception.message =~ /No route matches "\/puppet\/rdoc\/([^\/]+)\/classes\/(.+?)\.html/
render :template => "puppetclasses/no_route", :locals => {:environment => $1, :name => $2.gsub("/","::")}, :layout => false
else
local_request? ? rescue_action_locally(exception) : rescue_action_in_public(exception)
end
end
end
app/controllers/environments_controller.rb
class EnvironmentsController < ApplicationController
include Foreman::Controller::Environments
rescue_from ActionController::RoutingError, :with => :no_puppetclass_documentation_handler
before_filter :find_environment, :only => %w{show edit update destroy}
app/controllers/fact_values_controller.rb
class FactValuesController < ApplicationController
skip_before_filter :require_ssl, :only => :create
skip_before_filter :require_login, :only => :create
skip_before_filter :require_ssl, :only => :create
skip_before_filter :require_login, :only => :create
skip_before_filter :authorize, :only => :create
skip_before_filter :verify_authenticity_token, :only => :create
# avoids storing the facts data in the log files
app/controllers/hosts_controller.rb
:multiple_enable, :multiple_disable, :submit_multiple_disable, :submit_multiple_enable]
before_filter :find_host, :only => %w[show edit update destroy puppetrun setBuild cancelBuild report
reports facts storeconfig_klasses clone externalNodes pxe_config]
before_filter :authorize
filter_parameter_logging :root_pass
helper :hosts, :reports
def index
# restrict allowed hosts list based on the user permissions
@search = User.current.admin? ? Host.search(params[:search]) : Host.my_hosts.search(params[:search])
respond_to do |format|
@search = Host.search(params[:search])
format.html do
@hosts = @search.paginate :page => params[:page], :include => [:hostgroup, :domain, :operatingsystem, :environment, :model]
# You can see a host if you can CRUD it
@hosts = @search.paginate :page => params[:page], :include => [:hostgroup, :domain, :operatingsystem, :environment, :model, :fact_values]
@via = "fact_values_"
@last_reports = Report.maximum(:id, :group => :host_id, :conditions => {:host_id => @hosts})
end
......
hosts.delete_if {|host| host.destroy}
session[:selected] = []
flash[:foreman_notice] = hosts.empty? ? "Destroyed selected hosts" : "The following hosts were not deleted: #{hosts.map(&:name).join('<br/>')}"
missed_hosts = hosts.map(&:name).join('<br/>')
flash[:foreman_notice] = hosts.empty? ? "Destroyed selected hosts" : "The following hosts were not deleted: #{missed_hosts}"
redirect_to(hosts_path)
end
......
action = mode ? "enabled" : "disabled"
session[:selected] = []
flash[:foreman_notice] = @hosts.empty? ? "#{action.capitalize} selected hosts" : "The following hosts were not #{action}: #{hosts.map(&:name).join('<br/>')}"
missed_hosts = hosts.map(&:name).join('<br/>')
flash[:foreman_notice] = @hosts.empty? ? "#{action.capitalize} selected hosts" : "The following hosts were not #{action}: #{missed_hosts}"
redirect_to(hosts_path) and return
end
......
@search = list.search(params[:search])
respond_to do |format|
format.html do
@hosts = @search.paginate :page => params[:page], :include => [:hostgroup, :domain, :operatingsystem, :environment, :model]
@hosts = @search.paginate :page => params[:page], :include => [:hostgroup, :domain, :operatingsystem, :environment, :model, :fact_values]
@via = "fact_values_"
@last_reports = Report.maximum(:id, :group => :host_id, :conditions => {:host_id => @hosts})
@title = title
app/controllers/models_controller.rb
def destroy
@model = Model.find(params[:id])
if @model.destroy
if @model.destroy
flash[:foreman_notice] = "Successfully destroyed model."
else
flash[:foreman_error] = @model.errors.full_messages.join("<br/>")
app/controllers/notices_controller.rb
class NoticesController < ApplicationController
skip_before_filter :authorize, :only => :destroy
def destroy
@notice = Notice.find(params[:id])
if @notice.global
@notice.destroy
else
@notice.users.delete(current_user)
@notice.destroy unless @notice.users.any?
end
@notice.destroy_notice
redirect_to :back
end
end
app/controllers/puppetclasses_controller.rb
class PuppetclassesController < ApplicationController
include Foreman::Controller::Environments
rescue_from ActionController::RoutingError, :with => :no_puppetclass_documentation_handler
def index
respond_to do |format|
app/controllers/reports_controller.rb
class ReportsController < ApplicationController
skip_before_filter :require_login, :only => :create
skip_before_filter :require_ssl, :only => :create
skip_before_filter :require_login, :only => :create
skip_before_filter :require_ssl, :only => :create
skip_before_filter :authorize, :only => :create
skip_before_filter :verify_authenticity_token, :only => :create
helper :reports
app/controllers/roles_controller.rb
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class RolesController < ApplicationController
before_filter :require_admin
def index
@search = Role.search(params[:search])
@roles = @search.paginate(:page => params[:page], :order => "builtin ASC, name ASC")
end
def new
# Prefills the form with 'default user' role permissions
@role = Role.new({:permissions => Role.default_user.permissions})
@permissions = @role.setable_permissions
end
def create
@role = Role.new(params[:role])
@permissions = @role.setable_permissions
if @role.save
flash[:foreman_notice] = "#{@role.name} succcessfully created"
redirect_to roles_url
else
render :action => 'new'
end
end
def edit
@role = Role.find(params[:id])
@permissions = @role.setable_permissions
end
def update
@role = Role.find(params[:id])
if @role.update_attributes(params[:role])
flash[:foreman_notice] = "#{@role.name} successfully updated"
redirect_to roles_url
else
render :action => 'edit'
end
end
def destroy
@role = Role.find(params[:id])
if @role.destroy
flash[:foreman_notice] = "Successfully destroyed role."
else
flash[:foreman_error] = @role.errors.full_messages.join("<br/>")
end
redirect_to roles_url
end
def report
@roles = Role.all(:order => 'builtin, name')
@permissions = Foreman::AccessControl.permissions.select { |p| !p.public? }
if request.post?
@roles.each do |role|
role.permissions = params[:permissions][role.id.to_s]
role.save
end
flash[:foreman_notice] = "All non public permissions successfuly updated"
redirect_to roles_url
end
end
end
app/controllers/usergroups_controller.rb
class UsergroupsController < ApplicationController
def index
@usergroups = Usergroup.all
@usergroups = Usergroup.all(:order => "name")
end
def new
app/controllers/users_controller.rb
filter_parameter_logging :password, :password_confirmation
skip_before_filter :require_login, :only => [:login, :logout]
skip_before_filter :authorize, :only => [:login, :logout]
def index
# set defaults search order - cant use default scope due to bug in AR
......
@user = User.new(params[:user])
@user.admin = params[:admin]
if @user.save
@user.roles = Role.name_is("Anonymous")
flash[:foreman_notice] = "Successfully created user."
redirect_to users_url
else
......
def edit
@user = User.find(params[:id])
if @user.user_facts.count == 0
user_fact = @user.user_facts.build :operator => "==", :andor => "or"
user_fact.fact_name_id = Puppet::Rails::FactName.first.id if Puppet::Rails::FactName.first
true
end
end
def update
@user = User.find(params[:id])
admin = params[:user].delete :admin
# Remove keys for resticted variables when the user is granted minimal access only to their own account
if @minimal_edit
for key in params[:user].keys
params[:user].delete key unless %w{password_confirmation password mail firstname lastname}.include? key
end
end
if @user.update_attributes(params[:user])
@user.update_attribute :admin, admin
# Only an admin can update admin attribute of another use
# this is required, as the admin field is blacklisted above
@user.update_attribute(:admin, admin) if User.current.admin
flash[:foreman_notice] = "Successfully updated user."
redirect_to users_url
else
......
def destroy
user = User.find(params[:id])
if user == current_user
if user == User.current
flash[:foreman_notice] = "You are currently logged in, suicidal?"
redirect_to :back and return
end
......
# Called from the logout link
# Clears the rails session and redirects to the login action
def logout
session[:user] = @user = nil
session[:user] = @user = User.current = nil
if flash[:foreman_notice] or flash[:foreman_error]
flash.keep
else
session.clear
flash[:foreman_notice] = "Logged out - See you soon"
end
redirect_to login_users_path
......
end
end
private
def authorize(ctrl = params[:controller], action = params[:action])
# Minimal edit is true when the user is granted access to just their
# own account details
@minimal_edit = false
return true if User.current.allowed_to?({:controller => ctrl, :action => action})
if action =~ /edit|update/ and params[:id] == User.current.id.to_s
return @minimal_edit=true
else
deny_access and return
end
end
end
app/helpers/application_helper.rb
# Methods added to this helper will be available to all templates in the application.
# Methods added to this helper will be available to all templates in the application
module ApplicationHelper
def contract model
model.to_s
end
def graph(type,opts = {})
Gchart.send(type, {:size => '400x150', :bg => "E6DFCF", :format => "image_tag"}.merge(opts))
end
......
end
def edit_habtm klass, association
render :partial => 'common/edit_habtm', :locals =>{ :klass => klass, :associations => association.all.delete_if{|e| e == klass}}
render :partial => 'common/edit_habtm', :locals =>{ :klass => klass, :associations => association.all.sort.delete_if{|e| e == klass}}
end
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(image_tag("false.png", :title => "remove"), "remove_fields(this)")
end
# Creates a link to a javascript function that creates field entries for the association on the web page
# +name+ : String containing links's text
# +f+ : FormBuiler object
# +association : The field are created to allow entry into this association
# +partial+ : String containing an optional partial into which we render
def link_to_add_fields(name, f, association, partial = nil)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
......
:position => {:after => {:success => "selected_classes" }}
end
def check_all_links(form_name)
link_to_function("Check all", "checkAll('#{form_name}', true)") +
" | " +
link_to_function("Uncheck all", "checkAll('#{form_name}', false)")
end
def searchtab title, search, options
opts = {:action => params[:action], :tab_name => title, :search => search}
selected_class = options[:selected] ? "selectedtab" : ""
......
return param.to_i unless param.empty?
return @fact_name_id if @fact_name_id
end
# Return true if user is authorized for controller/action, otherwise false
# +controller+ : String or symbol for the controller
# +action+ : String or symbol for the action
def authorized_for(controller, action)
User.current.allowed_to?({:controller => controller, :action => action}) rescue false
end
# Display a link if user is authorized, otherwise a string
# +name+ : String to be displayed
# +options+ : Hash containing
# :enable_link : Boolean indicating whether the link is to be displayed
# :controlller : String or Symbol representing the controller
# :auth_action : String or Symbol representing the action to be used for authorization checks
# +html_options+ : Hash containing html options for the link or span
def link_to_if_authorized(name, options = {}, html_options = {})
enable_link = options.has_key?(:enable_link) ? options.delete(:enable_link) : true
auth_action = options.delete :auth_action
if enable_link
link_to_if authorized_for(options[:controller] || params[:controller], auth_action || options[:action]), name, options, html_options
else
content_tag(:span, name, {:class => "entry"}.merge(html_options))
end
end
# Display a link if user is authorized, otherwise nothing
# +name+ : String to be displayed
# +options+ : Hash containing
# :controlller : String or Symbol representing the controller
# :auth_action : String or Symbol representing the action to be used for authorization checks
# +html_options+ : Hash containing html options for the link or span
def display_link_if_authorized(name, options = {}, html_options = nil)
auth_action = options.delete :auth_action
link_to(name, options, html_options) if authorized_for(options[:controller] || params[:controller], auth_action || options[:action])
end
def authorized_edit_habtm klass, association
return edit_habtm(klass, association) if authorized_for params[:controller], params[:action]
show_habtm klass.send(association.name.pluralize.downcase)
end
end
app/helpers/common_parameters_helper.rb
module CommonParametersHelper
# Return true if user is authorized for controller/action OR controller/action@type, otherwise false
def authorized_via_my_scope(controller, action)
return true if authorized_for(controller, action)
operation = "#{action}_my_#{controller.singularize}".to_sym
User.current.allowed_to?(operation) and User.current.send(controller).include?(eval("@#{controller.singularize}"))
end
end
app/helpers/domains_helper.rb
module DomainsHelper
include CommonParametersHelper
end
app/helpers/host_groups_helper.rb
module HostGroupsHelper
include CommonParametersHelper
end
app/helpers/hostgroups_helper.rb
module HostgroupsHelper
include CommonParametersHelper
end
app/helpers/hosts_helper.rb
module HostsHelper
include CommonParametersHelper
def last_report_column(record)
return nil if record.last_report.nil?
time = time_ago_in_words(record.last_report.getlocal)
image_tag("#{not (record.error_count > 0 or record.no_report)}.png", :size => "18x18") +
link_to_if(@last_reports[record.id], time, report_path(@last_reports[record.id].to_i))
link_to_if_authorized(time, hash_for_report_path(:id => @last_reports[record.id], :enable_link => @last_reports[record.id])
)
end
# method that reformats the hostname column by adding the status icons
app/models/architecture.rb
class Architecture < ActiveRecord::Base
include Authorization
has_many :hosts
has_and_belongs_to_many :operatingsystems
validates_uniqueness_of :name
app/models/auth_source.rb
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class AuthSource < ActiveRecord::Base
include Authorization
has_many :users
validates_presence_of :name
......
end
# Try to authenticate a user not yet registered against available sources
# Returns : user's attributes OR nil
def self.authenticate(login, password)
AuthSource.find(:all).each do |source|
begin
app/models/auth_source_ldap.rb
self.port = 389 if self.port == 0
end
# Loads the LDAP info for a user and authenticates the user with their password
# Returns : Array of Strings.
# Either the users's DN or the user's full details OR nil
def authenticate(login, password)
return nil if login.blank? || password.blank?
attrs = []
app/models/authorization.rb
module Authorization
def self.included(base)
base.class_eval do
before_save :enforce_edit_permissions
before_destroy :enforce_destroy_permissions
before_create :enforce_create_permissions
end
end
# We must enforce the security model
def enforce_edit_permissions
enforce_permissions("edit") if enforce?
end
def enforce_destroy_permissions
enforce_permissions("destroy") if enforce?
end
def enforce_create_permissions
enforce_permissions("create") if enforce?
end
def enforce_permissions operation
# We get called again with the operation being set to create
return true if operation == "edit" and new_record?
klass = self.class.name.downcase
klass.gsub!(/authsource.*/, "authenticator")
klass.gsub!(/commonparameter.*/, "global_variable")
klasses = klass.pluralize
return true if User.current.allowed_to?("#{operation}_#{klasses}".to_sym)
errors.add_to_base "You do not have permission to #{operation} this #{klass}"
false
end
private
def enforce?
not (defined?(Rake) or User.current.admin?)
end
end
app/models/domain.rb
# This models a DNS domain and so represents a site.
class Domain < ActiveRecord::Base
include Authorization
has_many :hosts
has_many :subnets
has_many :domain_parameters, :dependent => :destroy, :foreign_key => :reference_id
has_and_belongs_to_many :users, :join_table => "user_domains"
accepts_nested_attributes_for :domain_parameters, :reject_if => lambda { |a| a[:value].blank? }, :allow_destroy => true
validates_uniqueness_of :name
validates_uniqueness_of :fullname, :allow_blank => true, :allow_nil => true
......
super({:only => [:name, :id]}.merge(options))
end
def enforce_permissions operation
# We get called again with the operation being set to create
return true if operation == "edit" and new_record?
current = User.current
if current.allowed_to?("#{operation}_domains".to_sym)
# If you can create domains then you can create them anywhere
return true if operation == "create"
# However if you are editing or destroying and you have a domain list then you are contrained
if current.domains.empty? or current.domains.map(&:id).include? self.id
return true
end
end
errors.add_to_base "You do not have permission to #{operation} this domain"
false
end
end
app/models/domain_parameter.rb
class DomainParameter < Parameter
belongs_to :domain, :foreign_key => :reference_id
validates_uniqueness_of :name, :scope => :reference_id
private
def enforce_permissions operation
# We get called again with the operation being set to create
return true if operation == "edit" and new_record?
current = User.current
if current.allowed_to?("#{operation}_domains".to_sym)
if current.domains.empty? or current.domains.include? domain
return true
end
end
errors.add_to_base "You do not have permission to #{operation} this domain parameter"
false
end
end
app/models/group_parameter.rb
class GroupParameter < Parameter
belongs_to :hostgroup, :foreign_key => :reference_id
validates_uniqueness_of :name, :scope => :reference_id
private
def enforce_permissions operation
# We get called again with the operation being set to create
return true if operation == "edit" and new_record?
current = User.current
if current.allowed_to?("#{operation}_hostgroups".to_sym)
if current.hostgroups.empty? or current.hostgroups.include? hostgroup
return true
end
end
errors.add_to_base "You do not have permission to #{operation} this group parameter"
false
end
end
app/models/host.rb
class Host < Puppet::Rails::Host
include Authorization
belongs_to :architecture
belongs_to :media
belongs_to :model
......
named_scope :successful, {:conditions => "puppet_status = 0"}
named_scope :alerts_disabled, {:conditions => ["enabled = ?", false] }
named_scope :my_hosts, lambda {
user = User.current
owner_conditions = sanitize_sql_for_conditions(["((hosts.owner_id in (?) AND hosts.owner_type = 'Usergroup') OR (hosts.owner_id = ? AND hosts.owner_type = 'User'))", user.my_usergroups.map(&:id), user.id])
domain_conditions = sanitize_sql_for_conditions([" (hosts.domain_id in (?))",dms = (user.domains).map(&:id)])
hostgroup_conditions = sanitize_sql_for_conditions([" (hosts.hostgroup_id in (?))",(hgs = user.hostgroups).map(&:id)])
fact_conditions = ""
for user_fact in (ufs = user.user_facts)
fact_conditions += sanitize_sql_for_conditions ["(hosts.id = fact_values.host_id and fact_values.fact_name_id = ? and fact_values.value #{user_fact.operator} ?)", user_fact.fact_name_id, user_fact.criteria]
fact_conditions = user_fact.andor == "and" ? "(#{fact_conditions}) and " : "#{fact_conditions} or "
end
if match = fact_conditions.match(/^(.*).....$/)
fact_conditions = "(#{match[1]})"
end
conditions = ""
if user.filtering?
conditions = "#{owner_conditions}" if user.filter_on_owner
(conditions = (user.domains_andor == "and") ? "(#{conditions}) and #{domain_conditions} " : "#{conditions} or #{domain_conditions} ") unless dms.empty?
(conditions = (user.hostgroups_andor == "and") ? "(#{conditions}) and #{hostgroup_conditions} " : "#{conditions} or #{hostgroup_conditions} ") unless hgs.empty?
(conditions = (user.facts_andor == "and") ? "(#{conditions}) and #{fact_conditions} " : "#{conditions} or #{fact_conditions} ") unless ufs.empty?
conditions.sub!(/\s*\(\)\s*/, "")
conditions.sub!(/^(?:\(\))?\s?(?:and|or)\s*/, "")
conditions.sub!(/\(\s*(?:or|and)\s*\(/, "((")
end
{:conditions => conditions}
}
# audit the changes to this model
acts_as_audited :except => [:last_report, :puppet_status, :last_compile]
......
validates_format_of :sp_name, :with => /.*-sp/, :allow_nil => true, :allow_blank => true
validates_presence_of :architecture_id, :domain_id, :mac, :operatingsystem_id
validates_length_of :root_pass, :minimum => 8,:too_short => 'should be 8 characters or more'
validates_format_of :mac, :with => /([a-f0-9]{1,2}:){5}[a-f0-9]{1,2}/
validates_format_of :ip, :with => /(\d{1,3}\.){3}\d{1,3}/
validates_format_of :mac, :with => (/([a-f0-9]{1,2}:){5}[a-f0-9]{1,2}/)
validates_format_of :ip, :with => (/(\d{1,3}\.){3}\d{1,3}/)
validates_presence_of :ptable, :message => "cant be blank unless a custom partition has been defined",
:if => Proc.new { |host| host.disk.empty? and not defined?(Rake) }
:if => Proc.new { |host| host.disk.empty? and not defined?(Rake) }
validates_format_of :sp_mac, :with => /([a-f0-9]{1,2}:){5}[a-f0-9]{1,2}/, :allow_nil => true, :allow_blank => true
validates_format_of :sp_ip, :with => /(\d{1,3}\.){3}\d{1,3}/, :allow_nil => true, :allow_blank => true
validates_format_of :serial, :with => /[01],\d{3,}n\d/, :message => "should follow this format: 0,9600n8", :allow_blank => true, :allow_nil => true
......
# supports a simple user, or a usergroup
# selection parameter is expected to be an ActiveRecord id_and_type method (see Foreman's AR extentions).
def is_owned_by=(selection)
oid = User.find(selection.to_i) if selection =~ /-Users$/
oid = Usergroup.find(selection.to_i) if selection =~ /-Usergroups$/
oid = User.find(selection.to_i) if selection =~ (/-Users$/)
oid = Usergroup.find(selection.to_i) if selection =~ (/-Usergroups$/)
self.owner = oid
end
......
# returns the list of puppetclasses a host is in.
def puppetclasses_names
return all_puppetclasses.collect {|c| c.name}
return all_puppetclasses.collect {|c| c.name}
end
def all_puppetclasses
return hostgroup.nil? ? puppetclasses : (hostgroup.puppetclasses + puppetclasses).uniq
return hostgroup.nil? ? puppetclasses : (hostgroup.puppetclasses + puppetclasses).uniq
end
# provide information about each node, mainly used for puppet external nodes
......
def fv name
v=fact_values.first(:select => "fact_values.value", :joins => :fact_name,
:conditions => "fact_names.name = '#{name}'")
:conditions => "fact_names.name = '#{name}'")
v.value unless v.nil?
end
......
end
def classes_from_storeconfigs
klasses = resources.find(:all, :conditions => {:restype => "Class"}, :select => :title, :order => :title)
klasses.map!(&:title).delete(:main)
return klasses
klasses = resources.find(:all, :conditions => {:restype => "Class"}, :select => :title, :order => :title)
klasses.map!(&:title).delete(:main)
return klasses
end
def can_be_build?
......
return hash
end
def enforce_permissions operation
if operation == "edit" and new_record?
return true # We get called again with the operation being set to create
end
current = User.current
if (operation == "edit") or operation == "destroy"
if current.allowed_to?("#{operation}_hosts".to_sym)
return true if Host.my_hosts(current).include? self
end
else # create
if current.allowed_to?(:create_hosts)
# We are unconstrained
return true if current.domains.empty? and current.hostgroups.empty?
# We are contrained and the constraint is matched
return true if (!current.domains.empty? and current.domains.include?(domain)) or
(!current.hostgroups.empty? and current.hostgroups.include?(hostgroup))
end
end
errors.add_to_base "You do not have permission to #{operation} this host"
false
end
private
# align common mac and ip address input
def normalize_addresses
......
return if name.empty? or domain.nil?
self.name += ".#{domain}" unless name =~ /.#{domain}$/
end
end
app/models/host_parameter.rb
validates_uniqueness_of :name, :scope => :reference_id
def to_s
"#{host_id ? host.name : "unassociated"}: #{name} = #{value}"
"#{host.id ? host.name : "unassociated"}: #{name} = #{value}"
end
private
def enforce_permissions operation
# We get called again with the operation being set to create
return true if operation == "edit" and new_record?
self.host.enforce_permissions operation
end
end
app/models/hostgroup.rb
class Hostgroup < ActiveRecord::Base
include Authorization
has_and_belongs_to_many :puppetclasses
has_and_belongs_to_many :users, :join_table => "user_hostgroups"
validates_uniqueness_of :name
validates_format_of :name, :with => /\A(\S+\s?)+\Z/, :message => "can't be blank or contain trailing white spaces."
has_many :group_parameters, :dependent => :destroy, :foreign_key => :reference_id
......
acts_as_audited
#TODO: add a method that returns the valid os for a hostgroup
#TODO: add a method that returns the valid os for a hostgroup
def all_puppetclasses
puppetclasses
end
def hostgroup
self
end
def all_puppetclasses
puppetclasses
end
def as_json(options={})
super({:only => [:name, :id]}.merge(options))
end
def hostgroup
self
end
end
app/models/media.rb
class Media < ActiveRecord::Base
include Authorization
has_and_belongs_to_many :operatingsystems
has_many :hosts
validates_uniqueness_of :name
app/models/model.rb
class Model < ActiveRecord::Base
include Authorization
has_many :hosts
before_destroy Ensure_not_used_by.new(:hosts)
validates_uniqueness_of :name
app/models/notice.rb
"#{global? ? "global" : "individual"} #{content}"
end
def destroy_notice
if global
destroy
else
users.delete(User.current)
destroy unless users.any?
end
end
private
def add_to_all_users
app/models/operatingsystem.rb
require 'uri'
class Operatingsystem < ActiveRecord::Base
include Authorization
has_many :hosts
has_and_belongs_to_many :medias
has_and_belongs_to_many :ptables
app/models/parameter.rb
class Parameter < ActiveRecord::Base
include Authorization
acts_as_audited
validates_presence_of :name, :value
validates_format_of :name, :value, :with => /^.*\S$/, :message => "can't be blank or contain trailing white space"
app/models/ptable.rb
# A host object may contain a reference to one of these ptables or, alternatively, it may contain a
# modified version of one of these in textual form
class Ptable < ActiveRecord::Base
include Authorization
has_many :hosts
has_and_belongs_to_many :operatingsystems
before_destroy Ensure_not_used_by.new(:hosts)
app/models/puppetclass.rb
class Puppetclass < ActiveRecord::Base
include Authorization
has_and_belongs_to_many :environments
has_and_belongs_to_many :operatingsystems
has_and_belongs_to_many :hosts
app/models/report.rb
class Report < ActiveRecord::Base
include Authorization
belongs_to :host
has_many :messages, :through => :logs, :dependent => :destroy
has_many :sources, :through => :logs, :dependent => :destroy
......
nil
end
# The metrics layout has changed in Puppet 2.6.x release,
# this method attempts to align the bit value metrics and the new name scheme in 2.6.x
# returns a hash of { :type => "metric type", :name => "metric_name"}
def self.translate_metrics_to26 metric
case metric
case metric
when "applied"
{ :type => "changes", :name => :total}
else
......
end
end
def enforce_permissions operation
# No one can edit a report
return false if operation == "edit"
# Anyone can create a report
return true if operation == "create"
return true if operation == "destroy" and User.current.allowed_to?(:destroy_reports)
errors.add_to_base "You do not have permission to #{operation} this report"
false
end
end
app/models/role.rb
# redMine - project management software
# Copyright (C) 2006 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Role < ActiveRecord::Base
# Built-in roles
BUILTIN_DEFAULT_USER = 1
BUILTIN_ANONYMOUS = 2
named_scope :givable, { :conditions => "builtin = 0", :order => 'name' }
named_scope :builtin, lambda { |*args|
compare = 'not' if args.first == true
{ :conditions => "#{compare} builtin = 0" }
}
before_destroy :check_deletable
has_many :user_roles, :dependent => :destroy
has_many :users, :through => :user_roles
serialize :permissions, Array
attr_protected :builtin
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :name, :maximum => 30
validates_format_of :name, :with => /^\w[\w\s\'\-]*\w$/i
validates_inclusion_of :builtin, :in => 0..2
def initialize *args
super *args
self.builtin = 0
end
def permissions
read_attribute(:permissions) || []
end
def permissions=(perms)
perms = perms.collect {|p| p.to_sym unless p.blank? }.compact.uniq if perms
write_attribute(:permissions, perms)
end
def add_permission!(*perms)
self.permissions = [] unless permissions.is_a?(Array)
permissions_will_change!
perms.each do |p|
p = p.to_sym
permissions << p unless permissions.include?(p)
end
save!
end
def remove_permission!(*perms)
return unless permissions.is_a?(Array)
permissions_will_change!
perms.each { |p| permissions.delete(p.to_sym) }
save!
end
# Returns true if the role has the given permission
def has_permission?(perm)
!permissions.nil? && permissions.include?(perm.to_sym)
end
# Return true if the role is a builtin role
def builtin?
self.builtin != 0
end
# Return true if the role is a user role
def user?
!self.builtin?
end
# Return true if role is allowed to do the specified action
# action can be:
# * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
# * a permission Symbol (eg. :edit_project)
def allowed_to?(action)
if action.is_a? Hash
allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
else
allowed_permissions.include? action
end
end
# Return all the permissions that can be given to the role
def setable_permissions
setable_permissions = Foreman::AccessControl.permissions - Foreman::AccessControl.public_permissions
setable_permissions -= Foreman::AccessControl.loggedin_only_permissions if self.builtin == BUILTIN_ANONYMOUS
setable_permissions
end
# Find all the roles that can be given to a user
def self.find_all_givable
find(:all, :conditions => {:builtin => 0}, :order => 'name')
end
# Return the builtin 'default user' role. If the role doesn't exist,
# it will be created on the fly.
def self.default_user
default_user_role = find(:first, :conditions => {:builtin => BUILTIN_DEFAULT_USER})
if default_user_role.nil?
default_user_role = create(:name => 'Default user') do |role|
role.builtin = BUILTIN_DEFAULT_USER
end
raise 'Unable to create the default user role.' if default_user_role.new_record?
end
default_user_role
end
# Return the builtin 'anonymous' role. If the role doesn't exist,
# it will be created on the fly.
def self.anonymous
anonymous_role = find(:first, :conditions => {:builtin => BUILTIN_ANONYMOUS})
if anonymous_role.nil?
anonymous_role = create(:name => 'Anonymous') do |role|
role.builtin = BUILTIN_ANONYMOUS
end
raise "Unable to create the anonymous role." if anonymous_role.new_record?
end
anonymous_role
end
private
def allowed_permissions
@allowed_permissions ||= permissions + Foreman::AccessControl.public_permissions.collect {|p| p.name}
end
def allowed_actions
@actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Foreman::AccessControl.allowed_actions(permission) }.flatten
end
def check_deletable
errors.add_to_base "Role is in use" if users.any?
errors.add_to_base "Can't delete builtin role" if builtin?
errors.empty?
end
end
app/models/subnet.rb
class Subnet < ActiveRecord::Base
include Authorization
has_many :hosts, :through => :domain
has_many :sps, :through => :hosts
#has_many :sps, :through => :hosts
belongs_to :domain
validates_presence_of :number, :mask
validates_uniqueness_of :number
......
validates_uniqueness_of :name, :scope => :domain_id
validates_associated :domain
before_destroy Ensure_not_used_by.new(:hosts, :sps)
before_destroy Ensure_not_used_by.new(:hosts) #, :sps)
# Subnets are displayed in the form of their network number/network mask
def to_label
app/models/user.rb
require 'digest/sha1'
class User < ActiveRecord::Base
include Authorization
attr_protected :password_hash, :password_salt, :admin
attr_accessor :password, :password_confirmation
......
has_many :usergroups, :through => :usergroup_member
has_many :direct_hosts, :as => :owner, :class_name => "Host"
has_and_belongs_to_many :notices, :join_table => 'user_notices'
has_many :user_roles
has_many :roles, :through => :user_roles
has_and_belongs_to_many :domains, :join_table => "user_domains"
has_and_belongs_to_many :hostgroups, :join_table => "user_hostgroups"
has_many :user_facts, :dependent => :destroy
has_many :facts, :through => :user_facts, :source => :fact_name
accepts_nested_attributes_for :user_facts, :reject_if => lambda { |a| a[:criteria].blank? }, :allow_destroy => true
validates_uniqueness_of :login, :message => "already exists"
validates_presence_of :login, :mail, :auth_source_id
......
before_destroy Ensure_not_used_by.new(:hosts), :ensure_admin_is_not_deleted
validate :name_used_in_a_usergroup
before_validation :prepare_password
after_destroy Proc.new {|user| user.domains.clear; user.hostgroups.clear}
cattr_accessor :current
def to_label
"#{firstname} #{lastname}"
......
alias_method :name, :to_label
def <=>(other)
self.name <=> other.name
self.name.downcase <=> other.name.downcase
end
# The text item to see in a select dropdown menu
......
def self.create_admin
email = SETTINGS[:administrator] || "root@" + Facter.domain
user = User.create(:login => "admin", :firstname => "Admin", :lastname => "User",
:mail => email, :auth_source => AuthSourceInternal.first, :password => "changeme")
:mail => email, :auth_source => AuthSourceInternal.first, :password => "changeme")
user.update_attribute :admin, true
user
end
# Tries to find the user in the DB and then authenticate against their authentication source
# If the user is not in the DB then try to login the user on each available athentication source
# If this succeeds then copy the user's details from the authentication source into the User table
# Returns : User object OR nil
def self.try_to_login(login, password)
# Make sure no one can sign in with an empty password
return nil if password.to_s.empty?
if user = find(:first, :conditions => ["login=?", login])
if user = find_by_login(login)
# user is already in local database
if user.auth_source
# user has an authentication method
return nil unless user.auth_source.authenticate(login, password)
if user.auth_source and user.auth_source.authenticate(login, password)
# user has an authentication method and the authentication was successful
User.current = user
user.update_attribute(:last_login_on, Time.now.utc)
else
user = nil
end
else
# user is not yet registered, try to authenticate with available sources
attrs = AuthSource.authenticate(login, password)
if attrs
user = new(*attrs)
# The default user must be given :create_users permissions for on-the-fly to work.
user.login = login
User.current = user
if user.save
user.reload
logger.info "User '#{user.login}' auto-created from #{user.auth_source}"
user.update_attribute(:last_login_on, Time.now.utc)
else
logger.info "Failed to save User '#{user.login}' #{user.errors.full_messages}"
user = nil
end
end
end
user.update_attribute(:last_login_on, Time.now.utc) if user and not user.new_record?
anonymous = Role.find_by_name("Anonymous")
User.current.roles << anonymous unless user.nil? or User.current.roles.include?(anonymous)
return user
rescue => text
raise text
......
self.password_hash == encrypt_password(pass)
end
def indirect_hosts
def my_usergroups
all_groups = []
for usergroup in usergroups
all_groups += usergroup.all_usergroups
end
all_groups.uniq.map{|g| g.hosts}.flatten.uniq
all_groups.uniq
end
def indirect_hosts
my_usergroups.map{|g| g.hosts}.flatten.uniq
end
def hosts
......
auth_source and auth_source.can_set_password?
end
# Return true if the user is allowed to do the specified action
# action can be:
# * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
# * a permission Symbol (eg. :edit_project)
def allowed_to?(action, options={})
return true if admin?
return false if roles.empty?
roles.detect {|role| role.allowed_to?(action)}
end
def logged?
true
end
# Indicates whether the user has host filtering enabled
# Returns : Boolean
def filtering?
filter_on_owner or
domains.any? or
hostgroups.any? or
facts.any?
end
private
def prepare_password
......
Digest::SHA1.hexdigest([pass, password_salt].join)
end
protected
def name_used_in_a_usergroup
if Usergroup.all.map(&:name).include?(self.login)
errors.add_to_base "A usergroup already exists with this name"
......
# admin account automatically
def ensure_admin_is_not_deleted
if login == "admin"
errors.add_to_base "Can't Delete Internal Admin account"
logger.warn "Unable to delete Internal Admin Account"
errors.add_to_base "Can't delete internal admin account"
logger.warn "Unable to delete internal admin account"
return false
end
end
app/models/user_fact.rb
class UserFact < ActiveRecord::Base
belongs_to :user
belongs_to :fact_name, :class_name => "Puppet::Rails::FactName"
validates_inclusion_of :andor, :in => %w{and or}
validates_inclusion_of :operator, :in => %w{= != > >= < <= }
validates_presence_of :fact_name
validates_presence_of :criteria
validates_presence_of :user
def initialize *args
super *args
operator = "=" if operator.empty?
andor = "or" if andor.empty?
end
def to_s
n = user.try(:name) || "Unknown user"
fn = fact_name.try(:name) || "Unknown fact"
"#{n}:#{fn}:#{criteria.empty? ? "Empty" : criteria}:#{operator}:#{andor}"
end
end
app/models/user_role.rb
# Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
... This diff was truncated because it exceeds the maximum size that can be displayed.
    (1-1/1)