summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xscripts/security_remove.pl189
1 files changed, 189 insertions, 0 deletions
diff --git a/scripts/security_remove.pl b/scripts/security_remove.pl
new file mode 100755
index 000000000..90099e387
--- /dev/null
+++ b/scripts/security_remove.pl
@@ -0,0 +1,189 @@
+#!/usr/bin/perl
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+use 5.10.1;
+use strict;
+use warnings;
+
+use FindBin '$RealBin';
+use lib "$RealBin/../..", "$RealBin/../../lib";
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Field;
+use Bugzilla::User;
+
+use Pod::Usage;
+
+# Load extensions for monkeypatched $user->clear_last_statistics_ts()
+BEGIN { Bugzilla->extensions(); }
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 1) {
+ die <<USAGE;
+Usage: security_remove.pl <user>
+
+E.g.: security_remove.pl foo\@bar.com
+
+will remove the specified user from the following roles on private only bugs:
+
+- Set reporter_accessible to false if user is the reporter
+- Remove from the cc list
+- Clear qa_contact if the user is qa_contact
+- Re-assign to nobody\@mozilla.org if user is the assignee
+
+This script should not touch user's membership or default assignee, qa contact,
+or cc settings for components.
+
+Script should not send any email about the changes.
+USAGE
+}
+
+my ($login_name) = @ARGV;
+
+# Load nobody user and set as current
+my $auto_user = Bugzilla::User->check({ name => 'automation@bmo.tld' });
+Bugzilla->set_user($auto_user);
+
+# Check target user
+my $target_user = Bugzilla::User->check({ name => $login_name });
+
+my $dbh = Bugzilla->dbh;
+my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+
+# Gather bug ids
+my $reporter_bugs = $dbh->selectcol_arrayref(
+ q{SELECT bugs.bug_id
+ FROM bugs, bug_group_map
+ WHERE bugs.bug_id = bug_group_map.bug_id
+ AND bugs.reporter_accessible = 1
+ AND bugs.reporter = ?},
+ undef, $target_user->id) || [];
+
+my $assignee_bugs = $dbh->selectcol_arrayref(
+ q{SELECT bugs.bug_id
+ FROM bugs, bug_group_map
+ WHERE bugs.bug_id = bug_group_map.bug_id
+ AND bugs.assigned_to = ?},
+ undef, $target_user->id) || [];
+
+my $qa_bugs = $dbh->selectcol_arrayref(
+ q{SELECT bugs.bug_id
+ FROM bugs, bug_group_map
+ WHERE bugs.bug_id = bug_group_map.bug_id
+ AND bugs.qa_contact = ?},
+ undef, $target_user->id) || [];
+
+my $cc_bugs = $dbh->selectcol_arrayref(
+ q{SELECT cc.bug_id
+ FROM cc, bug_group_map
+ WHERE cc.bug_id = bug_group_map.bug_id
+ AND cc.who = ?},
+ undef, $target_user->id) || [];
+
+my $reporter_count = scalar @$reporter_bugs;
+my $assignee_count = scalar @$assignee_bugs;
+my $qa_count = scalar @$qa_bugs;
+my $cc_count = scalar @$cc_bugs;
+
+if (!$reporter_count
+ && !$assignee_count
+ && !$qa_count
+ && !$cc_count)
+{
+ warn "There are no bugs to update.\n";
+ exit 1;
+}
+
+warn <<EOF;
+About to remove user from the following number of bugs:
+
+Reporter: $reporter_count
+Assignee: $assignee_count
+QA Contact: $qa_count
+CC: $cc_count
+
+Press <Ctrl-C> to stop or <Enter> to continue...
+EOF
+getc();
+
+$dbh->bz_start_transaction;
+
+# Reporter - set reporter_accessible to false
+my $field_id = get_field_id('reporter_accessible');
+foreach my $bug_id (@$reporter_bugs) {
+ warn "Updating bug $bug_id\n";
+ $dbh->do(
+ q{INSERT INTO bugs_activity (bug_id, who, bug_when, fieldid, removed, added)
+ VALUES (?, ?, ?, ?, ?, ?)},
+ undef, $bug_id, $auto_user->id, $timestamp, $field_id, 1, 0);
+ $dbh->do(
+ q{UPDATE bugs SET reporter_accessible = 0, delta_ts = ?, lastdiffed = ?
+ WHERE bug_id = ?},
+ undef, $timestamp, $timestamp, $bug_id);
+}
+
+# Assignee
+$field_id = get_field_id('assigned_to');
+foreach my $bug_id (@$assignee_bugs) {
+ warn "Updating bug $bug_id\n";
+ $dbh->do(
+ q{INSERT INTO bugs_activity (bug_id, who, bug_when, fieldid, removed, added)
+ VALUES (?, ?, ?, ?, ?, ?)},
+ undef, $bug_id, $auto_user->id, $timestamp, $field_id,
+ $target_user->login, $auto_user->login);
+ $dbh->do(
+ q{UPDATE bugs SET assigned_to = ?, delta_ts = ?, lastdiffed = ?
+ WHERE bug_id = ?},
+ undef, $auto_user->id, $timestamp, $timestamp, $bug_id);
+}
+
+# QA Contact
+$field_id = get_field_id('qa_contact');
+foreach my $bug_id (@$qa_bugs) {
+ warn "Updating bug $bug_id\n";
+ $dbh->do(
+ q{INSERT INTO bugs_activity (bug_id, who, bug_when, fieldid, removed, added)
+ VALUES (?, ?, ?, ?, ?, '')},
+ undef, $bug_id, $auto_user->id, $timestamp, $field_id, $target_user->login);
+ $dbh->do(
+ q{UPDATE bugs SET qa_contact = NULL, delta_ts = ?, lastdiffed = ?
+ WHERE bug_id = ?},
+ undef, $timestamp, $timestamp, $bug_id);
+}
+
+# CC list
+$field_id = get_field_id('cc');
+foreach my $bug_id (@$cc_bugs) {
+ warn "Updating bug $bug_id\n";
+ $dbh->do(
+ q{INSERT INTO bugs_activity (bug_id, who, bug_when, fieldid, removed, added)
+ VALUES (?, ?, ?, ?, ?, '')},
+ undef, $bug_id, $auto_user->id, $timestamp, $field_id, $target_user->login);
+ $dbh->do(q{DELETE FROM cc WHERE bug_id = ? AND who = ?},
+ undef, $bug_id, $target_user->id);
+}
+
+$target_user->clear_last_statistics_ts();
+
+$dbh->bz_commit_transaction;
+
+# It's complex to determine which items now need to be flushed from memcached.
+# As this is expected to be a rare event, we just flush the entire cache.
+Bugzilla->memcached->clear_all();
+
+__END__
+
+=head1 NAME
+
+security_remove.pl - Remove user from any role associated with private bugs.
+
+=head1 SYNOPSIS
+
+ security_remove.pl foo@bar.com