Project

General

Profile

Download (16.8 KB) Statistics
| Branch: | Tag: | Revision:
# rubocop:disable AccessModifierIndentation
#
# Copyright 2013 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public
# License as published by the Free Software Foundation; either version
# 2 of the License (GPLv2) or (at your option) any later version.
# There is NO WARRANTY for this software, express or implied,
# including the implied warranties of MERCHANTABILITY,
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
# have received a copy of GPLv2 along with this software; if not, see
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.

require 'util/password'

module Katello
module Concerns
module UserExtensions
extend ActiveSupport::Concern

included do

include Glue::Pulp::User if Katello.config.use_pulp
include Glue::ElasticSearch::User if Katello.config.use_elasticsearch
include Glue if Katello.config.use_cp || Katello.config.use_pulp
include ForemanTasks::Concerns::ActionSubject
include ForemanTasks::Concerns::ActionTriggering

def create_action
sync_action!
::Actions::Headpin::User::Create
end

include Ext::IndexedModel

include AsyncOrchestration
include Katello::Authorization::User
include Authorization::Enforcement
include Util::ThreadSession::UserModel

scope :hidden, where(:hidden => true)
scope :visible, where(:hidden => false)

# RAILS3458: THIS CHECK MUST BE THE FIRST before_destroy AND
# PROCEED DEPENDENT ASSOCIATIONS tinyurl.com/rails3458
before_destroy :not_last_super_user?, :destroy_own_role

has_many :roles_users, :dependent => :destroy, :class_name => Katello::RolesUser
has_many :katello_roles, :through => :roles_users, :before_remove => :super_admin_check, :uniq => true, :extend => RolesPermissions::UserOwnRole, :source => :role
has_many :help_tips, :dependent => :destroy, :class_name => "Katello::HelpTip"
has_many :user_notices, :dependent => :destroy, :class_name => "Katello::UserNotice"
has_many :notices, :through => :user_notices, :class_name => "Katello::Notice"
has_many :task_statuses, :dependent => :destroy, :class_name => "Katello::TaskStatus"
has_many :search_favorites, :dependent => :destroy, :class_name => "Katello::SearchFavorite"
has_many :search_histories, :dependent => :destroy, :class_name => "Katello::SearchHistory"
has_many :activation_keys, :dependent => :destroy, :class_name => "Katello::ActivationKey"
has_many :changeset_users, :dependent => :destroy, :class_name => "Katello::ChangesetUser"
belongs_to :default_environment, :class_name => "Katello::KTEnvironment", :inverse_of => :users
serialize :preferences, Hash

validates :default_locale, :inclusion => {:in => Katello.config.available_locales, :allow_nil => true, :message => _("must be one of %s") % Katello.config.available_locales.join(', ')}
validates_with Validators::OwnRolePresenceValidator, :attributes => :katello_roles

before_validation :create_own_role
after_validation :setup_remote_id
before_save :hash_password, :setup_preferences
after_save :create_or_update_default_system_registration_permission

# hash the password before creating or updateing the record
def hash_password
if Katello.config.warden != 'ldap'
self.password = Password.update(self.password) if self.password && self.password.length != 192
end
end

def setup_preferences
self.preferences = Hash.new unless self.preferences
end

def preferences_hash
self.preferences.is_a?(Hash) ? self.preferences : self.preferences.unserialized_value
end

def not_last_super_user?
if !User.current.nil?
if self.id == User.current.id
self.errors.add(:base, _("Cannot delete currently logged user"))
return false
end
end

unless self.can_be_deleted?
self.errors.add(:base, "cannot delete last admin user")
return false
end
return true
end

def not_ldap_mode?
return Katello.config.warden != 'ldap'
end

def ldap_mode?
!not_ldap_mode?
end

def own_role
katello_roles.find_own_role
end

def self.authenticate!(login, password)
u = User.where({ :login => login }).first
# check if user exists
return nil unless u
# check if not disabled
return nil if u.disabled
# check if we have password (can be set to nil for users from LDAP when you switch to DB)
return nil if u.password.nil?
# check if hash is valid
return nil unless Password.check(password, u.password)
u
end

# if the user authenticates with LDAP, log them in
def self.authenticate_using_ldap!(login, password)
if Ldap.valid_ldap_authentication? login, password
User.where(:login => login).first || create_ldap_user!(login)
else
nil
end
end

# an ldap user still needs a katello model
def self.create_ldap_user!(login)
# Some parts of user creation require a current user, but this method
# will never be called in that way
User.current ||= User.first
# user gets a dummy password and email
u = User.create!(:login => login)
User.current = u
u
end

def self.cp_oauth_header
fail Errors::UserNotSet, "unauthenticated to call a backend engine" if Thread.current[:cp_oauth_header].nil?
Thread.current[:cp_oauth_header]
end

def cp_oauth_header
{ 'cp-user' => self.username }
end

# is the current user consumer? (rhsm)
def self.consumer?
User.current.is_a? CpConsumerUser
end

def allowed_organizations
#test for all orgs
perms = Permission.joins(:role).joins("INNER JOIN #{Katello::RolesUser.table_name} ON #{Katello::RolesUser.table_name}.role_id = #{Katello::Role.table_name}.id").
where("#{Katello::RolesUser.table_name}.user_id = ?", self.id).where(:organization_id => nil).count
return Organization.without_deleting.all if perms > 0

Organization.without_deleting.joins(:permissions => {:role => :users}).where(:users => {:id => self.id}).uniq
end

def disable_helptip(key)
return if !self.helptips_enabled? #don't update helptips if user has it disabled
return if !Katello::HelpTip.where(:key => key, :user_id => self.id).empty?
help = Katello::HelpTip.new
help.key = key
help.user = self
help.save
end

#Remove up to 5 un-viewed notices
def pop_notices(organization = nil, count = 5)
notices = Notice.for_user(self).for_org(organization).unread.limit(count == :all ? nil : count)
notices.each { |notice| notice.user_notices.each(&:read!) }

notices = notices.map do |notice|
{:text => notice.text, :level => notice.level, :request_type => notice.request_type}
end
return notices
end

def enable_helptip(key)
return if !self.helptips_enabled? #don't update helptips if user has it disabled
help = Katello::HelpTip.where(:key => key, :user_id => self.id).first
return if help.nil?
help.destroy
end

def clear_helptips
Katello::HelpTip.destroy_all(:user_id => self.id)
end

def helptip_enabled?(key)
return self.helptips_enabled && Katello::HelpTip.where(:key => key, :user_id => self.id).first.nil?
end

def defined_roles
self.katello_roles - [self.own_role]
end

def defined_role_ids
self.katello_role_ids - [self.own_role.id]
end

def cp_oauth_header
{ 'cp-user' => self.login }
end

def send_password_reset
# generate a random password reset token that will be valid for only a configurable period of time
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!

UserMailer.send_password_reset(self)
end

def has_default_environment?
!default_environment.nil?
end

def create_or_update_default_system_registration_permission
return if default_environment.nil? || !default_environment.changed?
own_role.create_or_update_default_system_registration_permission(default_environment.organization, default_environment)
end

def default_locale
self.preferences_hash[:user][:locale] rescue nil
end

def default_locale=(locale)
self.preferences_hash[:user] = { } unless self.preferences_hash.key? :user
self.preferences_hash[:user][:locale] = locale
end

def legacy_mode
self.preferences_hash[:user][:legacy_mode] rescue nil
end

def legacy_mode=(use_legacy_mode)
self.preferences_hash[:user] = { } unless self.preferences_hash.key? :user
self.preferences_hash[:user][:legacy_mode] = use_legacy_mode.to_bool
end

def default_org
org_id = self.preferences_hash[:user][:default_org] rescue nil
if org_id && !org_id.nil? && org_id != "nil"
org = Organization.find_by_id(org_id)
return org if allowed_organizations.include?(org)
else
return nil
end
end

#set the default org if it's an actual org_id
def default_org=(org_id)
self.preferences_hash[:user] = { } unless self.preferences_hash.key? :user
if !org_id.nil? && org_id != "nil"
organization = Organization.find_by_id(org_id)
self.preferences_hash[:user][:default_org] = organization.id
else
self.preferences_hash[:user][:default_org] = nil
end
end

def subscriptions_match_system_preference
self.preferences_hash[:user][:subscriptions_match_system] rescue false
end

def subscriptions_match_system_preference=(flag)
self.preferences_hash[:user] = { } unless self.preferences_hash.key? :user
self.preferences_hash[:user][:subscriptions_match_system] = flag
end

def subscriptions_match_installed_preference
self.preferences_hash[:user][:subscriptions_match_installed] rescue false
end

def subscriptions_match_installed_preference=(flag)
self.preferences_hash[:user] = { } unless self.preferences_hash.key? :user
self.preferences_hash[:user][:subscriptions_match_installed] = flag
end

def subscriptions_no_overlap_preference
self.preferences_hash[:user][:subscriptions_no_overlap] rescue false
end

def subscriptions_no_overlap_preference=(flag)
self.preferences_hash[:user] = { } unless self.preferences_hash.key? :user
self.preferences_hash[:user][:subscriptions_no_overlap] = flag
end

def as_json(options)
super(options).merge 'default_organization' => default_environment.try(:organization).try(:name),
'default_environment' => default_environment.try(:name)
end

def has_superadmin_role?
katello_roles.any? { |r| r.superadmin? }
end

# verify the user is in the groups we are think they are in
# if not, reset them
def verify_ldap_roles
# get list of ldap_groups bound to roles the user is in
ldap_groups = LdapGroupRole.
joins(:role => :roles_users).
where(:katello_roles_users => { :ldap => true, :user_id => id }).
select(:ldap_group).
uniq.
map(&:ldap_group)

# make sure the user is still in those groups
# this operation is inexpensive compared to getting a new group list
if !Ldap.is_in_groups(self.login, ldap_groups)
# if user is not in these groups, flush their roles
# this is expensive
set_ldap_roles
else
return true
end
end

# flush existing ldap roles + load & save new ones
def set_ldap_roles
# first, delete existing ldap roles
clear_existing_ldap_roles!
# load groups from ldap
groups = Ldap.ldap_groups(self.login)
groups.each do |group|
# find corresponding
group_roles = LdapGroupRole.find_all_by_ldap_group(group)
group_roles.each do |group_role|
if group_role && !self.roles.reload.include?(group_role.role)
self.roles_users << RolesUser.new(:role => group_role.role, :user => self, :ldap => true)
end
end
end
self.save
end

def clear_existing_ldap_roles!
self.katello_roles = self.roles_users.select { |r| !r.ldap }.map { |r| r.role }
self.save!
end

def ldap_roles
roles_users.select { |r| r.ldap }.map { |r| r.role }
end

# returns the set of users who have kt_environment_id's environment set as their default
def self.with_default_environment(kt_environment_id)
where(:default_environment_id => kt_environment_id)
end

def create_or_update_search_history(path, search_params)
unless search_params.nil? || search_params.blank? || empty_display_attributes?(search_params)
if history = search_histories.find_or_create_by_path_and_params(path, search_params)
history.update_attributes(:updated_at => Time.now)
end
end
end

def empty_display_attributes?(a_search_string)
tokens = a_search_string.strip.split(/\s/)
return false if tokens.size > 1

return false unless tokens.first.end_with?(':')
true
end

protected

def can_be_deleted?
query = Katello::Permission.joins(:resource_type, :role).
joins("INNER JOIN #{Katello::RolesUser.table_name} ON #{Katello::RolesUser.table_name}.role_id = #{Katello::Role.table_name}.id").
where(:katello_resource_types => { :name => :all }, :organization_id => nil)
is_superadmin = query.where("#{Katello::RolesUser.table_name}.user_id" => id).count > 0
return true unless is_superadmin
more_than_one_supers = query.count > 1
more_than_one_supers
end

private

# generate a random token, that is unique within the User table for the column provided
def generate_token(column)
loop do
self[column] = SecureRandom.hex(32)
break unless User.exists?(column => self[column])
end
end

def log_roles(verbs, resource_type, tags, org, any_tags = false)
verbs_str = verbs ? verbs.join(',') : "perform any verb"
tags_str = "any tags"
if tags
tags_str = any_tags ? "any tag in #{tags.join(',')}" : "all the tags in #{tags.join(',')}"
end

org_str = org ? "organization #{org.name} (#{org.name})" : " any organization"
logger.debug "Checking if user #{login} is allowed to #{verbs_str} in #{resource_type.inspect} " +
"scoped for #{tags_str} in #{org_str}"
end

def create_own_role
return unless new_record?
katello_roles.find_or_create_own_role(self)
end

def destroy_own_role
katello_roles.destroy_own_role
end

def super_admin_check(role)
if role.superadmin? && role.users.length == 1
message = _("Cannot dissociate user '%{login}' from '%{role}' role. Need at least one user in the '%{role}' role.") % {:login => login, :role => role.name}
errors[:base] << message
fail ActiveRecord::RecordInvalid, self
end
end

def setup_remote_id
#if validation failed, don't setup
return false unless self.errors.empty?
if self.remote_id.nil?
self.remote_id = generate_remote_id
end
return true
end

def generate_remote_id
if User.current.object_id == self.object_id
# The case when the first user is being created.
Katello.config.pulp.default_login
elsif self.login.ascii_only?
"#{Util::Model.labelize(self.login)}-#{SecureRandom.hex(4)}"
else
Util::Model.uuid
end
end

def logger
::Logging.logger['roles']
end

end
end
end
end
(5-5/5)