]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1383108 - Sync security groups with Phabricator push connector
authorDavid Walsh <davidwalsh83@gmail.com>
Mon, 31 Jul 2017 21:44:31 +0000 (16:44 -0500)
committerdklawren <dklawren@users.noreply.github.com>
Mon, 31 Jul 2017 21:44:31 +0000 (17:44 -0400)
r=dkl

extensions/PhabBugz/lib/Util.pm
extensions/PhabBugz/lib/WebService.pm
extensions/Push/lib/Connector/Phabricator.pm

index cbbca7eab3adf5ed7e081f763f4e0231f6945dc1..75c523ad5a9ba4d39bce8e96360372f6540f4150 100644 (file)
@@ -20,6 +20,7 @@ use LWP::UserAgent;
 use base qw(Exporter);
 
 our @EXPORT = qw(
+    add_comment_to_revision
     create_revision_attachment
     create_private_revision_policy
     create_project
@@ -29,6 +30,7 @@ our @EXPORT = qw(
     get_project_phid
     get_revisions_by_ids
     intersect
+    make_revision_private
     make_revision_public
     request
     set_project_members
@@ -141,6 +143,23 @@ sub make_revision_public {
     });
 }
 
+sub make_revision_private {
+    my ($revision_phid) = @_;
+    return request('differential.revision.edit', {
+        transactions => [
+            {
+                type  => "view",
+                value => "admin"
+            },
+            {
+                type  => "edit",
+                value => "admin"
+            }
+        ],
+        objectIdentifier => $revision_phid
+    });
+}
+
 sub edit_revision_policy {
     my ($revision_phid, $policy_phid, $subscribers) = @_;
 
@@ -168,6 +187,21 @@ sub edit_revision_policy {
     return request('differential.revision.edit', $data);
 }
 
+sub add_comment_to_revision {
+    my ($revision_phid, $comment) = @_;
+
+    my $data = {
+        transactions => [
+            {
+                type  => 'comment',
+                value => $comment
+            }
+        ],
+        objectIdentifier => $revision_phid
+    };
+    return request('differential.revision.edit', $data);
+}
+
 sub get_project_phid {
     my $project = shift;
 
index 217ed18dc252465f2a24eb9a7c1a9d90d63050e5..11439ba706de0a6d4060f8f4e407f4f96db0589c 100644 (file)
@@ -17,6 +17,7 @@ use Bugzilla::Attachment;
 use Bugzilla::Bug;
 use Bugzilla::BugMail;
 use Bugzilla::Error;
+use Bugzilla::Extension::Push::Util qw(is_public);
 use Bugzilla::User;
 use Bugzilla::Util qw(correct_urlbase detaint_natural);
 use Bugzilla::WebService::Constants;
@@ -61,7 +62,7 @@ sub revision {
 
     # If bug is public then remove privacy policy
     my $result;
-    if (!@{ $bug->groups_in }) {
+    if (is_public($bug)) {
         $result = make_revision_public($revision_id);
     }
     # Else bug is private
index be0ea9b58cf62e2c4f1dc3144466e6d2a1f6de34..092d63dd3c9cf9f22ac10db3bcf2c2dd1dc339c5 100644 (file)
@@ -15,18 +15,22 @@ use base 'Bugzilla::Extension::Push::Connector::Base';
 
 use Bugzilla::Bug;
 use Bugzilla::Constants;
-use Bugzilla::Extension::PhabBugz::Util qw(intersect make_revision_public get_revisions_by_ids);
+use Bugzilla::Error;
+use Bugzilla::Extension::PhabBugz::Util qw(add_comment_to_revision
+  create_private_revision_policy edit_revision_policy get_bug_role_phids
+  get_revisions_by_ids intersect make_revision_public make_revision_private);
 use Bugzilla::Extension::Push::Constants;
-use Bugzilla::Extension::Push::Util;
+use Bugzilla::Extension::Push::Util qw(is_public);
 use Bugzilla::User;
 use List::Util qw(any);
 
-use constant PHAB_CONTENT_TYPE => 'text/x-phabricator-request';
+use constant PHAB_CONTENT_TYPE       => 'text/x-phabricator-request';
 use constant PHAB_ATTACHMENT_PATTERN => qr/^phabricator-D(\d+)/;
 
 sub options {
     return (
-        {   name     => 'phabricator_url',
+        {
+            name     => 'phabricator_url',
             label    => 'Phabricator URL',
             type     => 'string',
             default  => '',
@@ -40,11 +44,11 @@ sub should_send {
 
     return 0 unless Bugzilla->params->{phabricator_enabled};
 
-    return 0 unless $message->routing_key =~ /^(?:attachment|bug)\.modify:.*\bbug_group\b/;
+    return 0
+      unless $message->routing_key =~
+      /^(?:attachment|bug)\.modify:.*\bbug_group\b/;
 
-    my $data = $message->payload_decoded;
-    my $bug_data = $self->_get_bug_data($data) || return 0;
-    my $bug = Bugzilla::Bug->new( { id => $bug_data->{id}, cache => 1 } );
+    my $bug = $self->_get_bug_by_data( $message->payload_decoded ) || return 0;
 
     return $bug->has_attachment_with_mimetype(PHAB_CONTENT_TYPE);
 }
@@ -55,43 +59,101 @@ sub send {
     my $logger = Bugzilla->push_ext->logger;
 
     my $data = $message->payload_decoded;
-    my $bug_data = $self->_get_bug_data($data) || return 0;
-    my $bug = Bugzilla::Bug->new( { id => $bug_data->{id}, cache => 1 } );
+    my $bug = $self->_get_bug_by_data($data) || return PUSH_RESULT_OK;
+
+    my $is_public = is_public($bug);
+
+    my $phab_sync_groups = Bugzilla->params->{phabricator_sync_groups};
+    ThrowUserError('invalid_phabricator_sync_groups') unless $phab_sync_groups;
+
+    my $sync_group_names = [ split( '[,\s]+', $phab_sync_groups ) ];
+
+    my $bug_groups = $bug->groups_in;
+    my $bug_group_names = [ map { $_->name } @$bug_groups ];
+
+    my @set_groups = intersect( $bug_group_names, $sync_group_names );
+
+    if ( !$is_public && !@set_groups ) {
+        my $phab_error_message =
+          'Revision is being made private due to unknown Bugzilla groups.';
+
+        my @revisions = $self->_get_attachment_revisions($bug);
+        foreach my $revision (@revisions) {
+            add_comment_to_revision( $revision->{phid}, $phab_error_message );
+            make_revision_private( $revision->{phid} );
+        }
+
+        my $num_revisions = 0 + @revisions;
+        my $bmo_error_message =
+          ( $num_revisions > 1
+            ? 'Multiple revisions were'
+            : 'One revision was' )
+          . ' made private due to unknown Bugzilla groups.';
+
+        my $user =
+          Bugzilla->set_user(
+            Bugzilla::User->new( { name => 'conduit@mozilla.bugs' } ) );
+        $bug->add_comment( $bmo_error_message, { isprivate => 0 } );
+        my $bug_changes = $bug->update();
+        $bug->send_changes($bug_changes);
 
-    if(!is_public($bug)) {
-        $logger->info('Bailing on send because the bug is not public');
         return PUSH_RESULT_OK;
     }
 
+    my $policy_phid;
+    my $subscribers;
+    if ( !$is_public ) {
+        $policy_phid = create_private_revision_policy( $bug, \@set_groups );
+        $subscribers = get_bug_role_phids($bug);
+    }
+
+    my @revisions = $self->_get_attachment_revisions($bug);
+    foreach my $revision (@revisions) {
+        my $revision_phid = $revision->{phid};
+
+        if ($is_public) {
+            make_revision_public($revision_phid);
+        }
+        else {
+            edit_revision_policy( $revision_phid, $policy_phid, $subscribers );
+        }
+    }
+
+    return PUSH_RESULT_OK;
+}
+
+sub _get_attachment_revisions() {
+    my ( $self, $bug ) = @_;
+
+    my @revisions;
+
     my @attachments = grep {
-        $_->isobsolete == 0 &&
-        $_->contenttype eq PHAB_CONTENT_TYPE &&
-        $_->attacher->login eq 'phab-bot@bmo.tld'
+             $_->isobsolete == 0
+          && $_->contenttype eq PHAB_CONTENT_TYPE
+          && $_->attacher->login ne 'phab-bot@bmo.tld'
     } @{ $bug->attachments() };
 
-    if(@attachments){
-        my @rev_ids;
+    if (@attachments) {
+        my @revision_ids;
         foreach my $attachment (@attachments) {
-            my ($rev_id) = ($attachment->filename =~ PHAB_ATTACHMENT_PATTERN);
-            next if !$rev_id;
-            push(@rev_ids, int($rev_id));
+            my ($revision_id) =
+              ( $attachment->filename =~ PHAB_ATTACHMENT_PATTERN );
+            next if !$revision_id;
+            push( @revision_ids, int($revision_id) );
         }
 
-        if(@rev_ids) {
-            $logger->info('Getting info for revisions: ');
-            $logger->info(@rev_ids);
-
-            my @rev_details = get_revisions_by_ids(\@rev_ids);
-            foreach my $rev_detail (@rev_details) {
-                my $rev_phid = $rev_detail->{phid};
-                $logger->info('Making revision $rev_phid public:');
-                $logger->info($rev_phid);
-                make_revision_public($rev_phid);
-            }
+        if (@revision_ids) {
+            @revisions = get_revisions_by_ids( \@revision_ids );
         }
     }
 
-    return PUSH_RESULT_OK;
+    return @revisions;
+}
+
+sub _get_bug_by_data {
+    my ( $self, $data ) = @_;
+    my $bug_data = $self->_get_bug_data($data) || return 0;
+    my $bug = Bugzilla::Bug->new( { id => $bug_data->{id} } );
 }
 
 sub _get_bug_data {