diff options
Diffstat (limited to 'extensions/Push/lib/Connector.disabled')
-rw-r--r-- | extensions/Push/lib/Connector.disabled/AMQP.pm | 344 | ||||
-rw-r--r-- | extensions/Push/lib/Connector.disabled/ServiceNow.pm | 690 |
2 files changed, 514 insertions, 520 deletions
diff --git a/extensions/Push/lib/Connector.disabled/AMQP.pm b/extensions/Push/lib/Connector.disabled/AMQP.pm index 1ba365e21..dda73dade 100644 --- a/extensions/Push/lib/Connector.disabled/AMQP.pm +++ b/extensions/Push/lib/Connector.disabled/AMQP.pm @@ -20,211 +20,197 @@ use Bugzilla::Util qw(generate_random_password); use DateTime; sub init { - my ($self) = @_; - $self->{mq} = 0; - $self->{channel} = 1; - - if ($self->config->{queue}) { - $self->{queue_name} = $self->config->{queue}; - } else { - my $queue_name = Bugzilla->localconfig->{'urlbase'}; - $queue_name =~ s#^https?://##; - $queue_name =~ s#/$#|#; - $queue_name .= generate_random_password(16); - $self->{queue_name} = $queue_name; - } + my ($self) = @_; + $self->{mq} = 0; + $self->{channel} = 1; + + if ($self->config->{queue}) { + $self->{queue_name} = $self->config->{queue}; + } + else { + my $queue_name = Bugzilla->localconfig->{'urlbase'}; + $queue_name =~ s#^https?://##; + $queue_name =~ s#/$#|#; + $queue_name .= generate_random_password(16); + $self->{queue_name} = $queue_name; + } } sub options { - return ( - { - name => 'host', - label => 'AMQP Hostname', - type => 'string', - default => 'localhost', - required => 1, - }, - { - name => 'port', - label => 'AMQP Port', - type => 'string', - default => '5672', - required => 1, - validate => sub { - $_[0] =~ /\D/ && die "Invalid port (must be numeric)\n"; - }, - }, - { - name => 'username', - label => 'Username', - type => 'string', - default => 'guest', - required => 1, - }, - { - name => 'password', - label => 'Password', - type => 'password', - default => 'guest', - required => 1, - }, - { - name => 'vhost', - label => 'Virtual Host', - type => 'string', - default => '/', - required => 1, - }, - { - name => 'exchange', - label => 'Exchange', - type => 'string', - default => '', - required => 1, - }, - { - name => 'queue', - label => 'Queue', - type => 'string', - }, - ); + return ( + { + name => 'host', + label => 'AMQP Hostname', + type => 'string', + default => 'localhost', + required => 1, + }, + { + name => 'port', + label => 'AMQP Port', + type => 'string', + default => '5672', + required => 1, + validate => sub { + $_[0] =~ /\D/ && die "Invalid port (must be numeric)\n"; + }, + }, + { + name => 'username', + label => 'Username', + type => 'string', + default => 'guest', + required => 1, + }, + { + name => 'password', + label => 'Password', + type => 'password', + default => 'guest', + required => 1, + }, + { + name => 'vhost', + label => 'Virtual Host', + type => 'string', + default => '/', + required => 1, + }, + { + name => 'exchange', + label => 'Exchange', + type => 'string', + default => '', + required => 1, + }, + {name => 'queue', label => 'Queue', type => 'string',}, + ); } sub stop { - my ($self) = @_; - if ($self->{mq}) { - Bugzilla->push_ext->logger->debug('AMQP: disconnecting'); - $self->{mq}->disconnect(); - $self->{mq} = 0; - } + my ($self) = @_; + if ($self->{mq}) { + Bugzilla->push_ext->logger->debug('AMQP: disconnecting'); + $self->{mq}->disconnect(); + $self->{mq} = 0; + } } sub _connect { - my ($self) = @_; - my $logger = Bugzilla->push_ext->logger; - my $config = $self->config; - - $self->stop(); - - $logger->debug('AMQP: Connecting to RabbitMQ ' . $config->{host} . ':' . $config->{port}); - require Net::RabbitMQ; - my $mq = Net::RabbitMQ->new(); - $mq->connect( - $config->{host}, - { - port => $config->{port}, - user => $config->{username}, - password => $config->{password}, - } - ); - $self->{mq} = $mq; - - $logger->debug('AMQP: Opening channel ' . $self->{channel}); - $self->{mq}->channel_open($self->{channel}); - - $logger->debug('AMQP: Declaring queue ' . $self->{queue_name}); - $self->{mq}->queue_declare( - $self->{channel}, - $self->{queue_name}, - { - passive => 0, - durable => 1, - exclusive => 0, - auto_delete => 0, - }, - ); + my ($self) = @_; + my $logger = Bugzilla->push_ext->logger; + my $config = $self->config; + + $self->stop(); + + $logger->debug( + 'AMQP: Connecting to RabbitMQ ' . $config->{host} . ':' . $config->{port}); + require Net::RabbitMQ; + my $mq = Net::RabbitMQ->new(); + $mq->connect( + $config->{host}, + { + port => $config->{port}, + user => $config->{username}, + password => $config->{password}, + } + ); + $self->{mq} = $mq; + + $logger->debug('AMQP: Opening channel ' . $self->{channel}); + $self->{mq}->channel_open($self->{channel}); + + $logger->debug('AMQP: Declaring queue ' . $self->{queue_name}); + $self->{mq}->queue_declare($self->{channel}, $self->{queue_name}, + {passive => 0, durable => 1, exclusive => 0, auto_delete => 0,}, + ); } sub _bind { - my ($self, $message) = @_; - my $logger = Bugzilla->push_ext->logger; - my $config = $self->config; - - # bind to queue (also acts to verify the connection is still valid) - if ($self->{mq}) { - eval { - $logger->debug('AMQP: binding queue(' . $self->{queue_name} . ') with exchange(' . $config->{exchange} . ')'); - $self->{mq}->queue_bind( - $self->{channel}, - $self->{queue_name}, - $config->{exchange}, - $message->routing_key, - ); - }; - if ($@) { - $logger->debug('AMQP: ' . clean_error($@)); - $self->{mq} = 0; - } + my ($self, $message) = @_; + my $logger = Bugzilla->push_ext->logger; + my $config = $self->config; + + # bind to queue (also acts to verify the connection is still valid) + if ($self->{mq}) { + eval { + $logger->debug('AMQP: binding queue(' + . $self->{queue_name} + . ') with exchange(' + . $config->{exchange} + . ')'); + $self->{mq}->queue_bind( + $self->{channel}, $self->{queue_name}, + $config->{exchange}, $message->routing_key, + ); + }; + if ($@) { + $logger->debug('AMQP: ' . clean_error($@)); + $self->{mq} = 0; } + } } sub should_send { - my ($self, $message) = @_; - my $logger = Bugzilla->push_ext->logger; - - my $payload = $message->payload_decoded(); - my $target = $payload->{event}->{target}; - my $is_private = $payload->{$target}->{is_private} ? 1 : 0; - if (!$is_private && exists $payload->{$target}->{bug}) { - $is_private = $payload->{$target}->{bug}->{is_private} ? 1 : 0; - } - - if ($is_private) { - # we only want to push the is_private message from the change_set, as - # this is guaranteed to contain public information only - if ($message->routing_key !~ /\.modify:is_private$/) { - $logger->debug('AMQP: Ignoring private message'); - return 0; - } - $logger->debug('AMQP: Sending change of message to is_private'); + my ($self, $message) = @_; + my $logger = Bugzilla->push_ext->logger; + + my $payload = $message->payload_decoded(); + my $target = $payload->{event}->{target}; + my $is_private = $payload->{$target}->{is_private} ? 1 : 0; + if (!$is_private && exists $payload->{$target}->{bug}) { + $is_private = $payload->{$target}->{bug}->{is_private} ? 1 : 0; + } + + if ($is_private) { + + # we only want to push the is_private message from the change_set, as + # this is guaranteed to contain public information only + if ($message->routing_key !~ /\.modify:is_private$/) { + $logger->debug('AMQP: Ignoring private message'); + return 0; } - return 1; + $logger->debug('AMQP: Sending change of message to is_private'); + } + return 1; } sub send { - my ($self, $message) = @_; - my $logger = Bugzilla->push_ext->logger; - my $config = $self->config; - - # don't push comments to pulse - if ($message->routing_key =~ /^comment\./) { - $logger->debug('AMQP: Ignoring comment'); - return PUSH_RESULT_IGNORED; - } + my ($self, $message) = @_; + my $logger = Bugzilla->push_ext->logger; + my $config = $self->config; - # don't push private data - $self->should_push($message) - || return PUSH_RESULT_IGNORED; + # don't push comments to pulse + if ($message->routing_key =~ /^comment\./) { + $logger->debug('AMQP: Ignoring comment'); + return PUSH_RESULT_IGNORED; + } - $self->_bind($message); + # don't push private data + $self->should_push($message) || return PUSH_RESULT_IGNORED; - eval { - # reconnect if required - if (!$self->{mq}) { - $self->_connect(); - } - - # send message - $logger->debug('AMQP: Publishing message'); - $self->{mq}->publish( - $self->{channel}, - $message->routing_key, - $message->payload, - { - exchange => $config->{exchange}, - }, - { - content_type => 'text/plain', - content_encoding => '8bit', - }, - ); - }; - if ($@) { - return (PUSH_RESULT_TRANSIENT, clean_error($@)); + $self->_bind($message); + + eval { + # reconnect if required + if (!$self->{mq}) { + $self->_connect(); } - return PUSH_RESULT_OK; + # send message + $logger->debug('AMQP: Publishing message'); + $self->{mq}->publish( + $self->{channel}, $message->routing_key, $message->payload, + {exchange => $config->{exchange},}, + {content_type => 'text/plain', content_encoding => '8bit',}, + ); + }; + if ($@) { + return (PUSH_RESULT_TRANSIENT, clean_error($@)); + } + + return PUSH_RESULT_OK; } 1; diff --git a/extensions/Push/lib/Connector.disabled/ServiceNow.pm b/extensions/Push/lib/Connector.disabled/ServiceNow.pm index d0ebdcf10..032e47dde 100644 --- a/extensions/Push/lib/Connector.disabled/ServiceNow.pm +++ b/extensions/Push/lib/Connector.disabled/ServiceNow.pm @@ -32,403 +32,411 @@ use MIME::Base64; use Net::LDAP; use constant SEND_COMPONENTS => ( - { - product => 'mozilla.org', - component => 'Server Operations: Desktop Issues', - }, + {product => 'mozilla.org', component => 'Server Operations: Desktop Issues',}, ); sub options { - return ( - { - name => 'bugzilla_user', - label => 'Bugzilla Service-Now User', - type => 'string', - default => 'service.now@bugzilla.tld', - required => 1, - validate => sub { - Bugzilla::User->new({ name => $_[0] }) - || die "Invalid Bugzilla user ($_[0])\n"; - }, - }, - { - name => 'ldap_scheme', - label => 'Mozilla LDAP Scheme', - type => 'select', - values => [ 'LDAP', 'LDAPS' ], - default => 'LDAPS', - required => 1, - }, - { - name => 'ldap_host', - label => 'Mozilla LDAP Host', - type => 'string', - default => '', - required => 1, - }, - { - name => 'ldap_user', - label => 'Mozilla LDAP Bind Username', - type => 'string', - default => '', - required => 1, - }, - { - name => 'ldap_pass', - label => 'Mozilla LDAP Password', - type => 'password', - default => '', - required => 1, - }, - { - name => 'ldap_poll', - label => 'Mozilla LDAP Poll Frequency', - type => 'string', - default => '3', - required => 1, - help => 'minutes', - validate => sub { - $_[0] =~ /\D/ - && die "LDAP Poll Frequency must be an integer\n"; - $_[0] == 0 - && die "LDAP Poll Frequency cannot be less than one minute\n"; - }, - }, - { - name => 'service_now_url', - label => 'Service Now JSON URL', - type => 'string', - default => 'https://mozilladev.service-now.com', - required => 1, - help => "Must start with https:// and end with ?JSON", - validate => sub { - $_[0] =~ m#^https://[^\.\/]+\.service-now\.com\/# - || die "Invalid Service Now JSON URL\n"; - $_[0] =~ m#\?JSON$# - || die "Invalid Service Now JSON URL (must end with ?JSON)\n"; - }, - }, - { - name => 'service_now_user', - label => 'Service Now JSON Username', - type => 'string', - default => '', - required => 1, - }, - { - name => 'service_now_pass', - label => 'Service Now JSON Password', - type => 'password', - default => '', - required => 1, - }, - ); + return ( + { + name => 'bugzilla_user', + label => 'Bugzilla Service-Now User', + type => 'string', + default => 'service.now@bugzilla.tld', + required => 1, + validate => sub { + Bugzilla::User->new({name => $_[0]}) || die "Invalid Bugzilla user ($_[0])\n"; + }, + }, + { + name => 'ldap_scheme', + label => 'Mozilla LDAP Scheme', + type => 'select', + values => ['LDAP', 'LDAPS'], + default => 'LDAPS', + required => 1, + }, + { + name => 'ldap_host', + label => 'Mozilla LDAP Host', + type => 'string', + default => '', + required => 1, + }, + { + name => 'ldap_user', + label => 'Mozilla LDAP Bind Username', + type => 'string', + default => '', + required => 1, + }, + { + name => 'ldap_pass', + label => 'Mozilla LDAP Password', + type => 'password', + default => '', + required => 1, + }, + { + name => 'ldap_poll', + label => 'Mozilla LDAP Poll Frequency', + type => 'string', + default => '3', + required => 1, + help => 'minutes', + validate => sub { + $_[0] =~ /\D/ && die "LDAP Poll Frequency must be an integer\n"; + $_[0] == 0 && die "LDAP Poll Frequency cannot be less than one minute\n"; + }, + }, + { + name => 'service_now_url', + label => 'Service Now JSON URL', + type => 'string', + default => 'https://mozilladev.service-now.com', + required => 1, + help => "Must start with https:// and end with ?JSON", + validate => sub { + $_[0] =~ m#^https://[^\.\/]+\.service-now\.com\/# + || die "Invalid Service Now JSON URL\n"; + $_[0] =~ m#\?JSON$# + || die "Invalid Service Now JSON URL (must end with ?JSON)\n"; + }, + }, + { + name => 'service_now_user', + label => 'Service Now JSON Username', + type => 'string', + default => '', + required => 1, + }, + { + name => 'service_now_pass', + label => 'Service Now JSON Password', + type => 'password', + default => '', + required => 1, + }, + ); } sub options_validate { - my ($self, $config) = @_; - my $host = $config->{ldap_host}; - trick_taint($host); - my $scheme = lc($config->{ldap_scheme}); - eval { - my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die', timeout => 5) - or die $!; - $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass}); - }; - if ($@) { - die sprintf("Failed to connect to %s://%s/: %s\n", $scheme, $host, $@); - } + my ($self, $config) = @_; + my $host = $config->{ldap_host}; + trick_taint($host); + my $scheme = lc($config->{ldap_scheme}); + eval { + my $ldap + = Net::LDAP->new($host, scheme => $scheme, onerror => 'die', timeout => 5) + or die $!; + $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass}); + }; + if ($@) { + die sprintf("Failed to connect to %s://%s/: %s\n", $scheme, $host, $@); + } } my $_instance; sub init { - my ($self) = @_; - $_instance = $self; + my ($self) = @_; + $_instance = $self; } sub load_config { - my ($self) = @_; - $self->SUPER::load_config(@_); - $self->{bugzilla_user} ||= Bugzilla::User->new({ name => $self->config->{bugzilla_user} }); + my ($self) = @_; + $self->SUPER::load_config(@_); + $self->{bugzilla_user} + ||= Bugzilla::User->new({name => $self->config->{bugzilla_user}}); } sub should_send { - my ($self, $message) = @_; - - my $data = $message->payload_decoded; - my $bug_data = $self->_get_bug_data($data) - || return 0; - - # we don't want to send the initial comment in a separate message - # because we inject it into the inital message - if (exists $data->{comment} && $data->{comment}->{number} == 0) { - return 0; - } - - my $target = $data->{event}->{target}; - unless ($target eq 'bug' || $target eq 'comment' || $target eq 'attachment') { - return 0; - } - - # ensure the service-now user can see the bug - if (!$self->{bugzilla_user} || !$self->{bugzilla_user}->is_enabled) { - return 0; - } - $self->{bugzilla_user}->can_see_bug($bug_data->{id}) - || return 0; - - # don't push changes made by the service-now account - $data->{event}->{user}->{id} == $self->{bugzilla_user}->id - && return 0; - - # filter based on the component - my $bug = Bugzilla::Bug->new($bug_data->{id}); - my $send = 0; - foreach my $rh (SEND_COMPONENTS) { - if ($bug->product eq $rh->{product} && $bug->component eq $rh->{component}) { - $send = 1; - last; - } + my ($self, $message) = @_; + + my $data = $message->payload_decoded; + my $bug_data = $self->_get_bug_data($data) || return 0; + + # we don't want to send the initial comment in a separate message + # because we inject it into the inital message + if (exists $data->{comment} && $data->{comment}->{number} == 0) { + return 0; + } + + my $target = $data->{event}->{target}; + unless ($target eq 'bug' || $target eq 'comment' || $target eq 'attachment') { + return 0; + } + + # ensure the service-now user can see the bug + if (!$self->{bugzilla_user} || !$self->{bugzilla_user}->is_enabled) { + return 0; + } + $self->{bugzilla_user}->can_see_bug($bug_data->{id}) || return 0; + + # don't push changes made by the service-now account + $data->{event}->{user}->{id} == $self->{bugzilla_user}->id && return 0; + + # filter based on the component + my $bug = Bugzilla::Bug->new($bug_data->{id}); + my $send = 0; + foreach my $rh (SEND_COMPONENTS) { + if ($bug->product eq $rh->{product} && $bug->component eq $rh->{component}) { + $send = 1; + last; } - return $send; + } + return $send; } sub send { - my ($self, $message) = @_; - my $logger = Bugzilla->push_ext->logger; - my $config = $self->config; - - # should_send intiailises bugzilla_user; make sure we return a useful error message - if (!$self->{bugzilla_user}) { - return (PUSH_RESULT_TRANSIENT, "Invalid bugzilla-user (" . $self->config->{bugzilla_user} . ")"); - } - - # load the bug - my $data = $message->payload_decoded; - my $bug_data = $self->_get_bug_data($data); - my $bug = Bugzilla::Bug->new($bug_data->{id}); - - if ($message->routing_key eq 'bug.create') { - # inject the comment into the data for new bugs - my $comment = shift @{ $bug->comments }; - if ($comment->body ne '') { - $bug_data->{comment} = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($comment, 1); - } - - } elsif ($message->routing_key eq 'attachment.create') { - # inject the attachment payload - my $attachment = Bugzilla::Attachment->new($data->{attachment}->{id}); - $data->{attachment}->{data} = encode_base64($attachment->data); - } - - # map bmo login to ldap login and insert into json payload - $self->_add_ldap_logins($data, {}); - - # flatten json data - $self->_flatten($data); - - # add sysparm_action - $data->{sysparm_action} = 'insert'; - - if ($logger->debugging) { - $logger->debug(to_json(ref($data) ? $data : from_json($data), 1)); - } - - # send to service-now - my $request = HTTP::Request->new(POST => $self->config->{service_now_url}); - $request->content_type('application/json'); - $request->content(to_json($data)); - $request->authorization_basic($self->config->{service_now_user}, $self->config->{service_now_pass}); - - $self->{lwp} ||= LWP::UserAgent->new(agent => Bugzilla->localconfig->{urlbase}); - my $result = $self->{lwp}->request($request); - - # http level errors - if (!$result->is_success) { - # treat these as transient - return (PUSH_RESULT_TRANSIENT, $result->status_line); - } - - # empty response - if (length($result->content) == 0) { - # malformed request, treat as transient to allow code to fix - # may also be misconfiguration on servicenow, also transient - return (PUSH_RESULT_TRANSIENT, "Empty response"); + my ($self, $message) = @_; + my $logger = Bugzilla->push_ext->logger; + my $config = $self->config; + +# should_send intiailises bugzilla_user; make sure we return a useful error message + if (!$self->{bugzilla_user}) { + return (PUSH_RESULT_TRANSIENT, + "Invalid bugzilla-user (" . $self->config->{bugzilla_user} . ")"); + } + + # load the bug + my $data = $message->payload_decoded; + my $bug_data = $self->_get_bug_data($data); + my $bug = Bugzilla::Bug->new($bug_data->{id}); + + if ($message->routing_key eq 'bug.create') { + + # inject the comment into the data for new bugs + my $comment = shift @{$bug->comments}; + if ($comment->body ne '') { + $bug_data->{comment} + = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($comment, 1); } - # json errors - my $result_data; - eval { - $result_data = from_json($result->content); - }; - if ($@) { - return (PUSH_RESULT_TRANSIENT, clean_error($@)); - } - if ($logger->debugging) { - $logger->debug(to_json($result_data, 1)); - } - if (exists $result_data->{error}) { - return (PUSH_RESULT_ERROR, $result_data->{error}); - }; - - # malformed/unexpected json response - if (!exists $result_data->{records} - || ref($result_data->{records}) ne 'ARRAY' - || scalar(@{$result_data->{records}}) == 0 - ) { - return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: missing or empty 'records' array"); - } - - my $record = $result_data->{records}->[0]; - if (ref($record) ne 'HASH') { - return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: 'records' array does not contain an object"); - } + } + elsif ($message->routing_key eq 'attachment.create') { + + # inject the attachment payload + my $attachment = Bugzilla::Attachment->new($data->{attachment}->{id}); + $data->{attachment}->{data} = encode_base64($attachment->data); + } + + # map bmo login to ldap login and insert into json payload + $self->_add_ldap_logins($data, {}); + + # flatten json data + $self->_flatten($data); + + # add sysparm_action + $data->{sysparm_action} = 'insert'; + + if ($logger->debugging) { + $logger->debug(to_json(ref($data) ? $data : from_json($data), 1)); + } + + # send to service-now + my $request = HTTP::Request->new(POST => $self->config->{service_now_url}); + $request->content_type('application/json'); + $request->content(to_json($data)); + $request->authorization_basic($self->config->{service_now_user}, + $self->config->{service_now_pass}); + + $self->{lwp} ||= LWP::UserAgent->new(agent => Bugzilla->localconfig->{urlbase}); + my $result = $self->{lwp}->request($request); + + # http level errors + if (!$result->is_success) { + + # treat these as transient + return (PUSH_RESULT_TRANSIENT, $result->status_line); + } + + # empty response + if (length($result->content) == 0) { + + # malformed request, treat as transient to allow code to fix + # may also be misconfiguration on servicenow, also transient + return (PUSH_RESULT_TRANSIENT, "Empty response"); + } + + # json errors + my $result_data; + eval { $result_data = from_json($result->content); }; + if ($@) { + return (PUSH_RESULT_TRANSIENT, clean_error($@)); + } + if ($logger->debugging) { + $logger->debug(to_json($result_data, 1)); + } + if (exists $result_data->{error}) { + return (PUSH_RESULT_ERROR, $result_data->{error}); + } + + # malformed/unexpected json response + if (!exists $result_data->{records} + || ref($result_data->{records}) ne 'ARRAY' + || scalar(@{$result_data->{records}}) == 0) + { + return (PUSH_RESULT_ERROR, + "Malformed JSON response from ServiceNow: missing or empty 'records' array"); + } + + my $record = $result_data->{records}->[0]; + if (ref($record) ne 'HASH') { + return (PUSH_RESULT_ERROR, + "Malformed JSON response from ServiceNow: 'records' array does not contain an object" + ); + } - # sys_id is the unique identifier for this action - if (!exists $record->{sys_id} || $record->{sys_id} eq '') { - return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: 'records object' does not contain a valid sys_id"); - } + # sys_id is the unique identifier for this action + if (!exists $record->{sys_id} || $record->{sys_id} eq '') { + return (PUSH_RESULT_ERROR, + "Malformed JSON response from ServiceNow: 'records object' does not contain a valid sys_id" + ); + } - # success - return (PUSH_RESULT_OK, "sys_id: " . $record->{sys_id}); + # success + return (PUSH_RESULT_OK, "sys_id: " . $record->{sys_id}); } sub _get_bug_data { - my ($self, $data) = @_; - my $target = $data->{event}->{target}; - if ($target eq 'bug') { - return $data->{bug}; - } elsif (exists $data->{$target}->{bug}) { - return $data->{$target}->{bug}; - } else { - return; - } + my ($self, $data) = @_; + my $target = $data->{event}->{target}; + if ($target eq 'bug') { + return $data->{bug}; + } + elsif (exists $data->{$target}->{bug}) { + return $data->{$target}->{bug}; + } + else { + return; + } } sub _flatten { - # service-now expects a flat json object - my ($self, $data) = @_; - my $target = $data->{event}->{target}; + # service-now expects a flat json object + my ($self, $data) = @_; - # delete unnecessary deep objects - if ($target eq 'comment' || $target eq 'attachment') { - $data->{$target}->{bug_id} = $data->{$target}->{bug}->{id}; - delete $data->{$target}->{bug}; - } - delete $data->{event}->{changes}; + my $target = $data->{event}->{target}; - $self->_flatten_hash($data, $data, 'u'); + # delete unnecessary deep objects + if ($target eq 'comment' || $target eq 'attachment') { + $data->{$target}->{bug_id} = $data->{$target}->{bug}->{id}; + delete $data->{$target}->{bug}; + } + delete $data->{event}->{changes}; + + $self->_flatten_hash($data, $data, 'u'); } sub _flatten_hash { - my ($self, $base_hash, $hash, $prefix) = @_; - foreach my $key (keys %$hash) { - if (ref($hash->{$key}) eq 'HASH') { - $self->_flatten_hash($base_hash, $hash->{$key}, $prefix . "_$key"); - } elsif (ref($hash->{$key}) ne 'ARRAY') { - $base_hash->{$prefix . "_$key"} = $hash->{$key}; - } - delete $hash->{$key}; + my ($self, $base_hash, $hash, $prefix) = @_; + foreach my $key (keys %$hash) { + if (ref($hash->{$key}) eq 'HASH') { + $self->_flatten_hash($base_hash, $hash->{$key}, $prefix . "_$key"); + } + elsif (ref($hash->{$key}) ne 'ARRAY') { + $base_hash->{$prefix . "_$key"} = $hash->{$key}; } + delete $hash->{$key}; + } } sub _add_ldap_logins { - my ($self, $rh, $cache) = @_; - if (exists $rh->{login}) { - my $login = $rh->{login}; - $cache->{$login} ||= $self->_bmo_to_ldap($login); - Bugzilla->push_ext->logger->debug("BMO($login) --> LDAP(" . $cache->{$login} . ")"); - $rh->{ldap} = $cache->{$login}; - } - foreach my $key (keys %$rh) { - next unless ref($rh->{$key}) eq 'HASH'; - $self->_add_ldap_logins($rh->{$key}, $cache); - } + my ($self, $rh, $cache) = @_; + if (exists $rh->{login}) { + my $login = $rh->{login}; + $cache->{$login} ||= $self->_bmo_to_ldap($login); + Bugzilla->push_ext->logger->debug( + "BMO($login) --> LDAP(" . $cache->{$login} . ")"); + $rh->{ldap} = $cache->{$login}; + } + foreach my $key (keys %$rh) { + next unless ref($rh->{$key}) eq 'HASH'; + $self->_add_ldap_logins($rh->{$key}, $cache); + } } sub _bmo_to_ldap { - my ($self, $login) = @_; - my $ldap = $self->_ldap_cache(); + my ($self, $login) = @_; + my $ldap = $self->_ldap_cache(); - return '' unless $login =~ /\@mozilla\.(?:com|org)$/; + return '' unless $login =~ /\@mozilla\.(?:com|org)$/; - foreach my $check ($login, canon_email($login)) { - # check for matching bugmail entry - foreach my $mail (keys %$ldap) { - next unless $ldap->{$mail}{bugmail_canon} eq $check; - return $mail; - } + foreach my $check ($login, canon_email($login)) { - # check for matching mail - if (exists $ldap->{$check}) { - return $check; - } + # check for matching bugmail entry + foreach my $mail (keys %$ldap) { + next unless $ldap->{$mail}{bugmail_canon} eq $check; + return $mail; + } - # check for matching email alias - foreach my $mail (sort keys %$ldap) { - next unless grep { $check eq $_ } @{$ldap->{$mail}{aliases}}; - return $mail; - } + # check for matching mail + if (exists $ldap->{$check}) { + return $check; + } + + # check for matching email alias + foreach my $mail (sort keys %$ldap) { + next unless grep { $check eq $_ } @{$ldap->{$mail}{aliases}}; + return $mail; } + } - return ''; + return ''; } sub _ldap_cache { - my ($self) = @_; - my $logger = Bugzilla->push_ext->logger; - my $config = $self->config; - - # cache of all ldap entries; updated infrequently - if (!$self->{ldap_cache_time} || (time) - $self->{ldap_cache_time} > $config->{ldap_poll} * 60) { - $logger->debug('refreshing LDAP cache'); - - my $cache = {}; - - my $host = $config->{ldap_host}; - trick_taint($host); - my $scheme = lc($config->{ldap_scheme}); - my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die') - or die $!; - $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass}); - foreach my $ldap_base ('o=com,dc=mozilla', 'o=org,dc=mozilla') { - my $result = $ldap->search( - base => $ldap_base, - scope => 'sub', - filter => '(mail=*)', - attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'], - ); - foreach my $entry ($result->entries) { - my ($name, $bugMail, $mail, $type) = - map { $entry->get_value($_) || '' } - qw(cn bugzillaEmail mail employeeType); - next if $type eq 'DISABLED'; - $mail = lc $mail; - $bugMail = '' if $bugMail !~ /\@/; - $bugMail = trim($bugMail); - if ($bugMail =~ / /) { - $bugMail = (grep { /\@/ } split / /, $bugMail)[0]; - } - $name =~ s/\s+/ /g; - $cache->{$mail}{name} = trim($name); - $cache->{$mail}{bugmail} = $bugMail; - $cache->{$mail}{bugmail_canon} = canon_email($bugMail); - $cache->{$mail}{aliases} = []; - foreach my $alias ( - @{$entry->get_value('emailAlias', asref => 1) || []} - ) { - push @{$cache->{$mail}{aliases}}, canon_email($alias); - } - } - } + my ($self) = @_; + my $logger = Bugzilla->push_ext->logger; + my $config = $self->config; + + # cache of all ldap entries; updated infrequently + if (!$self->{ldap_cache_time} + || (time) - $self->{ldap_cache_time} > $config->{ldap_poll} * 60) + { + $logger->debug('refreshing LDAP cache'); - $self->{ldap_cache} = $cache; - $self->{ldap_cache_time} = (time); + my $cache = {}; + + my $host = $config->{ldap_host}; + trick_taint($host); + my $scheme = lc($config->{ldap_scheme}); + my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die') or die $!; + $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass}); + foreach my $ldap_base ('o=com,dc=mozilla', 'o=org,dc=mozilla') { + my $result = $ldap->search( + base => $ldap_base, + scope => 'sub', + filter => '(mail=*)', + attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'], + ); + foreach my $entry ($result->entries) { + my ($name, $bugMail, $mail, $type) + = map { $entry->get_value($_) || '' } qw(cn bugzillaEmail mail employeeType); + next if $type eq 'DISABLED'; + $mail = lc $mail; + $bugMail = '' if $bugMail !~ /\@/; + $bugMail = trim($bugMail); + if ($bugMail =~ / /) { + $bugMail = (grep {/\@/} split / /, $bugMail)[0]; + } + $name =~ s/\s+/ /g; + $cache->{$mail}{name} = trim($name); + $cache->{$mail}{bugmail} = $bugMail; + $cache->{$mail}{bugmail_canon} = canon_email($bugMail); + $cache->{$mail}{aliases} = []; + foreach my $alias (@{$entry->get_value('emailAlias', asref => 1) || []}) { + push @{$cache->{$mail}{aliases}}, canon_email($alias); + } + } } - return $self->{ldap_cache}; + $self->{ldap_cache} = $cache; + $self->{ldap_cache_time} = (time); + } + + return $self->{ldap_cache}; } 1; |