diff options
Diffstat (limited to 'extensions/Push/lib/Connector/ReviewBoard.pm')
-rw-r--r-- | extensions/Push/lib/Connector/ReviewBoard.pm | 214 |
1 files changed, 102 insertions, 112 deletions
diff --git a/extensions/Push/lib/Connector/ReviewBoard.pm b/extensions/Push/lib/Connector/ReviewBoard.pm index b5d1a9214..97f489826 100644 --- a/extensions/Push/lib/Connector/ReviewBoard.pm +++ b/extensions/Push/lib/Connector/ReviewBoard.pm @@ -12,67 +12,88 @@ use warnings; use base 'Bugzilla::Extension::Push::Connector::Base'; +use Bugzilla::Bug; +use Bugzilla::BugMail; +use Bugzilla::Component; use Bugzilla::Constants; use Bugzilla::Extension::Push::Constants; use Bugzilla::Extension::Push::Util; -use Bugzilla::Bug; -use Bugzilla::Attachment; -use Bugzilla::Extension::Push::Connector::ReviewBoard::Client; - -use JSON 'decode_json'; -use DateTime; -use Scalar::Util 'blessed'; +use Bugzilla::Group; +use Bugzilla::Product; +use Bugzilla::User; +use Bugzilla::Util qw( trim ); use constant RB_CONTENT_TYPE => 'text/x-review-board-request'; - -sub client { - my $self = shift; - - $self->{client} //= Bugzilla::Extension::Push::Connector::ReviewBoard::Client->new( - base_uri => $self->config->{base_uri}, - username => $self->config->{username}, - password => $self->config->{password}, - $self->config->{proxy} ? (proxy => $self->config->{proxy}) : (), - ); - - return $self->{client}; -} +use constant AUTOMATION_USER => 'automation@bmo.tld'; sub options { return ( { - name => 'base_uri', - label => 'Base URI for ReviewBoard', + name => 'product', + label => 'Product to create bugs in', type => 'string', - default => 'https://reviewboard.allizom.org', + default => 'Developer Services', required => 1, + validate => sub { + Bugzilla::Product->new({ name => $_[0] }) + || die "Invalid Product ($_[0])\n"; + }, }, { - name => 'username', - label => 'Username', + name => 'component', + label => 'Component to create bugs in', type => 'string', - default => 'guest', + default => 'MozReview', required => 1, + validate => sub { + my ($component, $config) = @_; + my $product = Bugzilla::Product->new({ name => $config->{product} }) + || die "Invalid Product (" . $config->{product} . ")\n"; + Bugzilla::Component->new({ product => $product, name => $component }) + || die "Invalid Component ($component)\n"; + }, }, { - name => 'password', - label => 'Password', - type => 'password', - default => 'guest', + name => 'version', + label => "The bug's version", + type => 'string', + default => 'Production', required => 1, + validate => sub { + my ($version, $config) = @_; + my $product = Bugzilla::Product->new({ name => $config->{product} }) + || die "Invalid Product (" . $config->{product} . ")\n"; + Bugzilla::Version->new({ product => $product, name => $version }) + || die "Invalid Version ($version)\n"; + }, }, { - name => 'proxy', - label => 'Proxy', - type => 'string', + name => 'group', + label => 'Security group', + type => 'string', + default => 'mozilla-employee-confidential', + required => 1, + validate => sub { + Bugzilla::Group->new({ name => $_[0] }) + || die "Invalid Group ($_[0])\n"; + }, + }, + { + name => 'cc', + label => 'Comma separated list of users to CC', + type => 'string', + default => '', + required => 1, + validate => sub { + foreach my $login (map { trim($_) } split(',', $_[0])) { + Bugzilla::User->new({ name => $login }) + || die "Invalid User ($login)\n"; + } + }, }, ); } -sub stop { - my ($self) = @_; -} - sub should_send { my ($self, $message) = @_; @@ -102,86 +123,55 @@ sub send { my $payload = $message->payload_decoded(); my $target = $payload->{event}->{target}; - if (my $method = $self->can("_process_$target")) { - $self->$method($payload->{$target}); + # load attachments + my $bug_id = $target eq 'bug' ? $payload->{bug}->{id} : $payload->{attachment}->{bug}->{id}; + my $attach_id = $target eq 'attachment' ? $payload->{attachment}->{id} : undef; + Bugzilla->set_user(Bugzilla::User->super_user); + my $bug = Bugzilla::Bug->new({ id => $bug_id, cache => 1 }); + Bugzilla->logout; + + # create a bug if there are any mozreview attachments + my @reviews = grep { $_->contenttype eq RB_CONTENT_TYPE } @{ $bug->attachments }; + if (@reviews) { + + # build comment + my $comment = $target eq 'bug' + ? "Bug $bug_id has MozReview reviews and is no longer public." + : "MozReview attachment $attach_id on Bug $bug_id is no longer public."; + $comment .= "\n\n"; + foreach my $attachment (@reviews) { + $comment .= $attachment->data . "\n"; + } + + # create bug + my $user = Bugzilla::User->new({ name => AUTOMATION_USER, cache => 1 }); + die "Invalid User: " . AUTOMATION_USER . "\n" unless $user; + Bugzilla->set_user($user); + my $new_bug = Bugzilla::Bug->create({ + short_desc => "[SECURITY] Bug $bug_id is no longer public", + product => $config->{product}, + component => $config->{component}, + bug_severity => 'normal', + groups => [ map { trim($_) } split(',', $config->{group}) ], + op_sys => 'Unspecified', + rep_platform => 'Unspecified', + version => $config->{version}, + cc => [ map { trim($_) } split(',', $config->{cc}) ], + comment => $comment, + }); + Bugzilla::BugMail::Send($new_bug->id, { changer => Bugzilla->user }); + Bugzilla->logout; + + $logger->info("Created bug " . $new_bug->id); } }; - if ($@) { - return (PUSH_RESULT_TRANSIENT, clean_error($@)); + my $error = $@; + Bugzilla->logout; + if ($error) { + return (PUSH_RESULT_TRANSIENT, clean_error($error)); } return PUSH_RESULT_OK; } -sub _process_attachment { - my ($self, $payload_target) = @_; - my $logger = Bugzilla->push_ext->logger; - my $attachment = blessed($payload_target) - ? $payload_target - : Bugzilla::Attachment->new({ id => $payload_target->{id}, cache => 1 }); - - if ($attachment) { - my $content = $attachment->data; - my $base_uri = quotemeta($self->config->{base_uri}); - if (my ($id) = $content =~ m|$base_uri/r/([0-9]+)|) { - my $resp = $self->client->review_request->delete($id); - my $content = $resp->decoded_content; - my $status = $resp->code; - my $result = $content && decode_json($content) ; - - if ($status == 204) { - # Success, review request deleted! - $logger->debug("Deleted review request $id"); - } - elsif ($status == 404) { - # API error 100 - Does Not Exist - $logger->debug("Does Not Exist: Review Request $id does not exist"); - } - elsif ($status == 403) { - # API error 101 - Permission Denied - $logger->error("Permission Denied: ReviewBoard Push Connector may be misconfigured"); - die $result->{err}{msg}; - } - elsif ($status == 401) { - # API error 103 - Not logged in - $logger->error("Not logged in: ReviewBoard Push Connector may be misconfigured"); - die $result->{err}{msg}; - } - else { - if ($result) { - my $code = $result->{err}{code}; - my $msg = $result->{err}{msg}; - $logger->error("Unexpected API Error: ($code) $msg"); - die $msg; - } - else { - $logger->error("Unexpected HTTP Response $status"); - die "HTTP Status: $status"; - } - } - } - else { - $logger->error("Cannot find link: ReviewBoard Push Connector may be misconfigured"); - die "Unable to find link in $content"; - } - } - else { - $logger->error("Cannot find attachment with id = $payload_target->{id}"); - } -} - -sub _process_bug { - my ($self, $payload_target) = @_; - - Bugzilla->set_user(Bugzilla::User->super_user); - my $bug = Bugzilla::Bug->new({ id => $payload_target->{id}, cache => 1 }); - my @attachments = @{ $bug->attachments }; - Bugzilla->logout; - - foreach my $attachment (@attachments) { - next if $attachment->contenttype ne RB_CONTENT_TYPE; - $self->_process_attachment($attachment); - } -} - 1; |