summaryrefslogtreecommitdiffstats
path: root/scripts/group-set-members.pl
blob: 3271b2e242644b336cac940645519c5fbb299fcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/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 strict;
use warnings;
use feature 'say';
use FindBin;
use lib "$FindBin::Bin/../..";
use lib "$FindBin::Bin/../../lib";

use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::User;
use Bugzilla::Group;
use Getopt::Long qw(:config gnu_getopt);

Bugzilla->usage_mode(USAGE_MODE_CMDLINE);

my ($users_file, $group, $admin);
my ($do_adds, $do_removes) = (0, 0);

GetOptions('admin=s'      => \$admin,
           'users-file=s' => \$users_file,
           'do-adds'      => \$do_adds,
           'do-removes'   => \$do_removes,
           'group=s'      => \$group);

usage() unless $admin && $users_file && $group;

Bugzilla->set_user(Bugzilla::User->check({name => $admin}));

my $group_obj = Bugzilla::Group->check({name => $group});

my %old_member = map { $_->name => $_ } @{$group_obj->members_direct()};
my %new_member;
my @missing;

open my $fh, '<', $users_file or die "Unable to open $users_file: $!";
while (my $user_name = <$fh>) {
    chomp $user_name;
    eval {
        my $user = Bugzilla::User->check({name => $user_name});
        $new_member{ $user->name } = $user;
    };
    if ($@) {
        push @missing, $user_name;
    }
}

my @removes = map  { $old_member{$_} } grep { !$new_member{$_} } keys %old_member;
my @adds    = map  { $new_member{$_} } grep { !$old_member{$_} } keys %new_member;

if (@removes == 0 && @adds == 0) {
    if (@missing != 0) {
        printf STDERR "There are %d user(s) in %s that do not exist.\n",
          scalar @missing, $users_file;
    }
    say STDERR "Nothing to do\n";
    exit;
}

$| = 1;
printf STDERR "Group '%s', Admin '%s'\n", $group, $admin;
printf STDERR "Will add %d user(s)\n", scalar @adds if $do_adds;
printf STDERR "Will remove %d user(s)\n", scalar @removes if $do_removes;
printf STDERR "There are %d user(s) in %s that do not exist.\n", scalar @missing, $users_file
  if @missing;
say STDERR "Press <Ctrl-C> to stop or <Enter> to continue...";
getc();

say "missing $_\n" foreach @missing;

my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction();

if ($do_removes) {
    foreach my $remove (@removes) {
        say "remove ", $remove->login, " from ", $group;
        $remove->set_groups({ remove => [$group] });
        $remove->update;
    }
}

if ($do_adds) {
    foreach my $add (@adds) {
        say "add ", $add->login, " to ", $group;
        $add->set_groups({ add => [$group] });
        $add->update;
    }
}

$dbh->bz_commit_transaction();

say STDERR "done.\n";

Bugzilla->memcached->clear_all();

sub usage {
    die <<EOF;
usage $0 --admin bob\@mozilla.org --users-file users.txt --group pants

--users-file  File containing one bugzilla email per line.
--admin      Admin user capable of adding people to the group.
--group      Group name to add users from user.txt into.
--do-adds    Add users in users-file to the group.
--do-removes Remove users NOT in users-file from the group.

Informational messages are sent to STDERR. STDOUT should be redirected to a file
as it will contain a list of which users were added, removed, and any missing users.
EOF
}