Project

General

Profile

« Previous | Next » 

Revision d51d3c9b

Added by Timo Goebel over 6 years ago

fixes #20653 - ui notifications for hosts with usergroup owner

View differences:

app/models/host/base.rb
scope :no_organization, -> { rewhere(:organization_id => nil) }
delegate :ssh_authorized_keys, :to => :owner, :allow_nil => true
delegate :notification_recipients_ids, :to => :owner, :allow_nil => true
PRIMARY_INTERFACE_ATTRIBUTES = [:name, :ip, :ip6, :mac,
:subnet, :subnet_id, :subnet_name,
app/models/notification.rb
# This class' responsibility is, given a notification blueprint, to determine
# who are the notification recipients
class Notification < ApplicationRecord
AUDIENCE_USER = 'user'
AUDIENCE_GROUP = 'usergroup'
AUDIENCE_TAXONOMY = 'taxonomy'
AUDIENCE_GLOBAL = 'global'
AUDIENCE_ADMIN = 'admin'
AUDIENCE_USER = 'user'
AUDIENCE_USERGROUP = 'usergroup'
AUDIENCE_GLOBAL = 'global'
AUDIENCE_ADMIN = 'admin'
# calls notification_recipients_ids on the subject to
# determine the recipient user ids
AUDIENCE_SUBJECT = 'subject'
belongs_to :notification_blueprint
belongs_to :initiator, :class_name => User, :foreign_key => 'user_id'
......
validates :notification_blueprint, :presence => true
validates :initiator, :presence => true
validates :audience, :inclusion => {
:in => [AUDIENCE_USER, AUDIENCE_GROUP, AUDIENCE_TAXONOMY,
:in => [AUDIENCE_USER, AUDIENCE_USERGROUP, AUDIENCE_SUBJECT,
AUDIENCE_GLOBAL, AUDIENCE_ADMIN]
}, :presence => true
validates :message, :presence => true
......
case audience
when AUDIENCE_GLOBAL
User.reorder('').pluck(:id)
when AUDIENCE_TAXONOMY
subject.user_ids.uniq
when AUDIENCE_USER
[initiator.id]
when AUDIENCE_ADMIN
User.unscoped.only_admin.except_hidden.reorder('').uniq.pluck(:id)
when AUDIENCE_GROUP
subject.all_users.uniq.map(&:id) # This needs to be rewritten in usergroups.
else
subject.try(:notification_recipients_ids) || []
end
end
app/models/taxonomy.rb
(self.send("#{type.downcase}_parameters".to_sym).authorized(:view_params) + taxonomy_inherited_params_objects.to_a.reverse!).uniq {|param| param.name}
end
def notification_recipients_ids
self.subtree.flat_map(&:users).map(&:id).uniq
end
private
delegate :need_to_be_selected_ids, :selected_ids, :used_and_selected_ids, :mismatches, :missing_ids, :check_for_orphans,
app/models/user.rb
{ login => super }
end
def notification_recipients_ids
[self.id]
end
private
def prepare_password
app/models/usergroup.rb
all_users.flat_map(&:ssh_keys)
end
def notification_recipients_ids
all_users.map(&:id)
end
protected
# Recurses down the tree of usergroups and finds the users
app/services/ui_notifications.rb
# Do not break actions using notifications even if there is a failure.
logger.warn("Failed to handle notifications - this is most likely a bug: #{e}")
logger.debug(e.backtrace.join("\n"))
false
end
def self.logger
app/services/ui_notifications/hosts.rb
module Hosts
class Base < UINotifications::Base
def deliver!
if audience.nil? || initiator.nil?
unless subject.owner
logger.warn("Invalid owner for #{subject}, unable to send notifications")
# add notification for missing owner
UINotifications::Hosts::MissingOwner.deliver!(subject)
......
protected
def audience
case subject.owner_type
when 'User'
::Notification::AUDIENCE_USER
when 'Usergroup'
::Notification::AUDIENCE_GROUP
end
::Notification::AUDIENCE_SUBJECT if subject.owner
end
def initiator
app/services/ui_notifications/hosts/destroy.rb
Notification.create!(
initiator: initiator,
audience: audience,
# note we do not store the subject, as the object is being deleted.
subject: subject.owner, # note we store the host owner, as the host object is being deleted.
message: StringParser.new(blueprint.message, {subject: subject}),
notification_blueprint: blueprint
)
end
def audience
case subject.owner_type
when 'User'
::Notification::AUDIENCE_USER
when 'Usergroup'
::Notification::AUDIENCE_USERGROUP
end
end
def delete_others
logger.debug("Removing all notifications for host: #{subject}")
Notification.where(subject: subject).destroy_all
test/models/notification_test.rb
end
test 'user notifications should subscribe only to itself' do
notification = FactoryGirl.build(:notification,
:audience => Notification::AUDIENCE_USER)
assert_equal [notification.initiator.id], notification.subscriber_ids
notification = FactoryGirl.create(:notification,
:subject => User.current,
:audience => Notification::AUDIENCE_USER)
assert_equal [User.current.id], notification.subscriber_ids
end
test 'usergroup notifications should subscribe to all of its members' do
group = FactoryGirl.create(:usergroup)
group.users = FactoryGirl.create_list(:user,25)
notification = FactoryGirl.build(:notification,
:audience => Notification::AUDIENCE_GROUP)
:audience => Notification::AUDIENCE_USERGROUP)
notification.subject = group
assert group.all_users.any?
assert_equal group.all_users.map(&:id),
notification.subscriber_ids
assert_equal group.all_users.map(&:id).sort,
notification.subscriber_ids.sort
end
test 'Organization notifications should subscribe to all of its members' do
org = FactoryGirl.create(:organization)
org.users = FactoryGirl.create_list(:user,25)
notification = FactoryGirl.build(:notification,
:audience => Notification::AUDIENCE_TAXONOMY)
:audience => Notification::AUDIENCE_SUBJECT)
notification.subject = org
assert org.user_ids.any?
assert_equal org.user_ids, notification.subscriber_ids
assert_equal org.user_ids.sort, notification.subscriber_ids.sort
end
test 'Location notifications should subscribe to all of its members' do
loc = FactoryGirl.create(:location)
loc.users = FactoryGirl.create_list(:user,25)
notification = FactoryGirl.build(:notification,
:audience => Notification::AUDIENCE_TAXONOMY)
:audience => Notification::AUDIENCE_SUBJECT)
notification.subject = loc
assert loc.user_ids.any?
assert_equal loc.user_ids, notification.subscriber_ids
assert_equal loc.user_ids.sort, notification.subscriber_ids.sort
end
test 'Global notifications should subscribe to all users' do
notification = FactoryGirl.build(:notification,
:audience => Notification::AUDIENCE_GLOBAL)
assert User.count > 0
assert_equal User.reorder('').pluck(:id),
notification.subscriber_ids
assert_equal User.reorder('').pluck(:id).sort,
notification.subscriber_ids.sort
end
test 'Admin notifications should subscribe to all admin users except hidden' do
test/unit/ui_notifications/hosts/base_test.rb
require 'test_helper'
class UINotificationsHostsTest < ActiveSupport::TestCase
test 'notification audience should be user' do
host.owner = FactoryGirl.build(:user)
assert_equal 'user', audience
class TestNotification < ::UINotifications::Hosts::Base
def create
::Notification.create!(
initiator: initiator,
subject: subject,
audience: audience,
notification_blueprint: blueprint
)
end
def blueprint
@blueprint ||= FactoryGirl.create(:notification_blueprint)
end
end
test 'notification audience should be usergroup' do
host.owner = FactoryGirl.build(:usergroup)
assert_equal 'usergroup', audience
test 'notification audience should be SUBJECT if owner is present' do
host.owner = FactoryGirl.build(:user)
assert_equal 'subject', audience
end
test 'notification audience should be nil if there is no owner' do
......
assert !base.deliver!
end
describe 'deliver notification to host owner' do
test 'owner is single user' do
host.owner = FactoryGirl.create(:user)
assert_difference("NotificationRecipient.all.count", 1) do
assert TestNotification.new(host).deliver!
end
end
test 'owner is usergroup' do
group = FactoryGirl.create(:usergroup)
group.users = FactoryGirl.create_list(:user, 5)
host.owner = group
assert_difference("NotificationRecipient.all.count", 5) do
assert TestNotification.new(host).deliver!
end
end
end
private
def host

Also available in: Unified diff