RSS

(root)/bmo/4.2 : /editwhines.cgi (revision 8095)

To get this branch, use:
bzr branch /bmo/4.2
Line Revision Contents
1 2750
#!/usr/bin/perl -wT
2
# -*- Mode: perl; indent-tabs-mode: nil -*-
3
#
4
# The contents of this file are subject to the Mozilla Public
5
# License Version 1.1 (the "License"); you may not use this file
6
# except in compliance with the License. You may obtain a copy of
7
# the License at http://www.mozilla.org/MPL/
8
#
9
# Software distributed under the License is distributed on an "AS
10
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11
# implied. See the License for the specific language governing
12
# rights and limitations under the License.
13
#
14
# The Original Code is the Bugzilla Bug Tracking System.
15
#
16
# The Initial Developer of the Original Code is Netscape Communications
17
# Corporation. Portions created by Netscape are
18
# Copyright (C) 1998 Netscape Communications Corporation. All
19
# Rights Reserved.
20
#
21
# Contributor(s): Erik Stambaugh <erik@dasbistro.com>
22
#
23
24
################################################################################
25
# Script Initialization
26
################################################################################
27
28
use strict;
29
30 5304
use lib qw(. lib);
31 2750
32 4293
use Bugzilla;
33 2750
use Bugzilla::Constants;
34 4296
use Bugzilla::Util;
35
use Bugzilla::Error;
36 2750
use Bugzilla::User;
37 3119
use Bugzilla::Group;
38 4612
use Bugzilla::Token;
39 6809
use Bugzilla::Whine::Schedule;
40 6889
use Bugzilla::Whine::Query;
41 7270
use Bugzilla::Whine;
42 4296
43 2750
# require the user to have logged in
44 3684
my $user = Bugzilla->login(LOGIN_REQUIRED);
45 2750
46
###############################################################################
47
# Main Body Execution
48
###############################################################################
49
50
my $cgi      = Bugzilla->cgi;
51
my $template = Bugzilla->template;
52 3762
my $vars     = {};
53 2750
my $dbh      = Bugzilla->dbh;
54
55
my $userid   = $user->id;
56 4612
my $token    = $cgi->param('token');
57 2750
my $sth; # database statement handle
58
59 7270
# $events is a hash ref of Bugzilla::Whine objects keyed by event id,
60
# that stores the active user's events.
61 2750
#
62
# Eventually, it winds up with:
63
#  'queries'  - array ref containing hashes of:
64
#       'name'          - the name of the saved query
65
#       'title'         - The title line for the search results table
66
#       'sort'          - Numeric sort ID
67
#       'id'            - row ID for the query entry
68
#       'onemailperbug' - whether a single message must be sent for each
69
#                         result.
70
#  'schedule' - array ref containing hashes of:
71
#       'day' - Day or range of days this schedule will be run
72
#       'time' - time or interval to run
73 3119
#       'mailto_type' - MAILTO_USER or MAILTO_GROUP
74
#       'mailto' - person/group who will receive the results
75 2750
#       'id' - row ID for the schedule
76
my $events = get_events($userid);
77
78
# First see if this user may use whines
79 3684
$user->in_group('bz_canusewhines')
80 3001
  || ThrowUserError("auth_failure", {group  => "bz_canusewhines",
81
                                     action => "schedule",
82
                                     object => "reports"});
83 2750
84
# May this user send mail to other users?
85 4523
my $can_mail_others = Bugzilla->user->in_group('bz_canusewhineatothers');
86 2750
87
# If the form was submitted, we need to look for what needs to be added or
88
# removed, then what was altered.
89
90
if ($cgi->param('update')) {
91 4612
    check_token_data($token, 'edit_whine');
92
93 2750
    if ($cgi->param("add_event")) {
94
        # we create a new event
95
        $sth = $dbh->prepare("INSERT INTO whine_events " .
96
                             "(owner_userid) " .
97
                             "VALUES (?)");
98
        $sth->execute($userid);
99
    }
100
    else {
101
        for my $eventid (keys %{$events}) {
102
            # delete an entire event
103
            if ($cgi->param("remove_event_$eventid")) {
104
                # We need to make sure these belong to the same user,
105
                # otherwise we could simply delete whatever matched that ID.
106
                #
107
                # schedules
108 6809
                my $schedules = Bugzilla::Whine::Schedule->match({ eventid => $eventid });
109 2750
                $sth = $dbh->prepare("DELETE FROM whine_schedules "
110
                    . "WHERE id=?");
111 6809
                foreach my $schedule (@$schedules) {                    
112
                    $sth->execute($schedule->id);
113 2750
                }
114
115
                # queries
116
                $sth = $dbh->prepare("SELECT whine_queries.id " .
117
                                     "FROM whine_queries " .
118
                                     "LEFT JOIN whine_events " .
119
                                     "ON whine_events.id = " .
120
                                     "whine_queries.eventid " .
121
                                     "WHERE whine_events.id = ? " .
122
                                     "AND whine_events.owner_userid = ?");
123
                $sth->execute($eventid, $userid);
124 6809
                my @ids = @{$sth->fetchall_arrayref};
125 2750
                $sth = $dbh->prepare("DELETE FROM whine_queries " .
126
                                     "WHERE id=?");
127
                for (@ids) {
128
                    my $delete_id = $_->[0];
129
                    $sth->execute($delete_id);
130
                }
131
132
                # events
133
                $sth = $dbh->prepare("DELETE FROM whine_events " .
134
                                     "WHERE id=? AND owner_userid=?");
135
                $sth->execute($eventid, $userid);
136
            }
137
            else {
138 6547
                # check the subject, body and mailifnobugs for changes
139 2750
                my $subject = ($cgi->param("event_${eventid}_subject") or '');
140
                my $body    = ($cgi->param("event_${eventid}_body")    or '');
141 6547
                my $mailifnobugs = $cgi->param("event_${eventid}_mailifnobugs") ? 1 : 0;
142 2750
143
                trick_taint($subject) if $subject;
144
                trick_taint($body)    if $body;
145
146 7270
                if ( ($subject ne $events->{$eventid}->subject)
147
                  || ($mailifnobugs != $events->{$eventid}->mail_if_no_bugs)
148
                  || ($body    ne $events->{$eventid}->body) ) {
149 2750
150
                    $sth = $dbh->prepare("UPDATE whine_events " .
151 6547
                                         "SET subject=?, body=?, mailifnobugs=? " .
152 2750
                                         "WHERE id=?");
153 6547
                    $sth->execute($subject, $body, $mailifnobugs, $eventid);
154 2750
                }
155
156
                # add a schedule
157
                if ($cgi->param("add_schedule_$eventid")) {
158
                    # the schedule table must be locked before altering
159
                    $sth = $dbh->prepare("INSERT INTO whine_schedules " .
160 3119
                                         "(eventid, mailto_type, mailto, " .
161 2750
                                         "run_day, run_time) " .
162 3119
                                         "VALUES (?, ?, ?, 'Sun', 2)");
163
                    $sth->execute($eventid, MAILTO_USER, $userid);
164 2750
                }
165
                # add a query
166
                elsif ($cgi->param("add_query_$eventid")) {
167
                    $sth = $dbh->prepare("INSERT INTO whine_queries "
168
                        . "(eventid) "
169
                        . "VALUES (?)");
170
                    $sth->execute($eventid);
171
                }
172
            }
173
174
            # now check all of the schedules and queries to see if they need
175
            # to be altered or deleted
176
177
            # Check schedules for changes
178 6809
            my $schedules = Bugzilla::Whine::Schedule->match({ eventid => $eventid });
179 2750
            my @scheduleids = ();
180 6809
            foreach my $schedule (@$schedules) {
181
                push @scheduleids, $schedule->id;
182 3119
            }
183 2750
184
            # we need to double-check all of the user IDs in mailto to make
185
            # sure they exist
186
            my $arglist = {};   # args for match_field
187
            for my $sid (@scheduleids) {
188 3119
                if ($cgi->param("mailto_type_$sid") == MAILTO_USER) {
189
                    $arglist->{"mailto_$sid"} = {
190
                        'type' => 'single',
191
                    };
192
                }
193 2750
            }
194
            if (scalar %{$arglist}) {
195 6943
                Bugzilla::User::match_field($arglist);
196 2750
            }
197
198
            for my $sid (@scheduleids) {
199
                if ($cgi->param("remove_schedule_$sid")) {
200 3437
                    # having the assignee id in here is a security failsafe
201 2750
                    $sth = $dbh->prepare("SELECT whine_schedules.id " .
202
                                         "FROM whine_schedules " .
203
                                         "LEFT JOIN whine_events " .
204
                                         "ON whine_events.id = " .
205
                                         "whine_schedules.eventid " .
206
                                         "WHERE whine_events.owner_userid=? " .
207
                                         "AND whine_schedules.id =?");
208
                    $sth->execute($userid, $sid);
209
210
                    my @ids = @{$sth->fetchall_arrayref};
211
                    for (@ids) {
212
                        $sth = $dbh->prepare("DELETE FROM whine_schedules " .
213
                                             "WHERE id=?");
214
                        $sth->execute($_->[0]);
215
                    }
216
                }
217
                else {
218 3470
                    my $o_day         = $cgi->param("orig_day_$sid") || '';
219
                    my $day           = $cgi->param("day_$sid") || '';
220 3948
                    my $o_time        = $cgi->param("orig_time_$sid") || 0;
221
                    my $time          = $cgi->param("time_$sid") || 0;
222 3470
                    my $o_mailto      = $cgi->param("orig_mailto_$sid") || '';
223
                    my $mailto        = $cgi->param("mailto_$sid") || '';
224
                    my $o_mailto_type = $cgi->param("orig_mailto_type_$sid") || 0;
225
                    my $mailto_type   = $cgi->param("mailto_type_$sid") || 0;
226 3119
227
                    my $mailto_id = $userid;
228
229
                    # get an id for the mailto address
230
                    if ($can_mail_others && $mailto) {
231
                        if ($mailto_type == MAILTO_USER) {
232 6194
                            $mailto_id = login_to_id($mailto);
233 3119
                        }
234
                        elsif ($mailto_type == MAILTO_GROUP) {
235 6194
                            # The group name is used in a placeholder.
236
                            trick_taint($mailto);
237
                            $mailto_id = Bugzilla::Group::ValidateGroupName($mailto, ($user))
238
                                           || ThrowUserError('invalid_group_name', { name => $mailto });
239 3119
                        }
240
                        else {
241
                            # bad value, so it will just mail to the whine
242
                            # owner.  $mailto_id was already set above.
243
                            $mailto_type = MAILTO_USER;
244
                        }
245 2750
                    }
246
247 3119
                    detaint_natural($mailto_type);
248
249 2750
                    if ( ($o_day  ne $day) ||
250 3119
                         ($o_time ne $time) ||
251 3470
                         ($o_mailto ne $mailto) ||
252 3119
                         ($o_mailto_type != $mailto_type) ){
253 2750
254 3470
                        trick_taint($day);
255
                        trick_taint($time);
256 2750
257
                        # the schedule table must be locked
258
                        $sth = $dbh->prepare("UPDATE whine_schedules " .
259
                                             "SET run_day=?, run_time=?, " .
260 3119
                                             "mailto_type=?, mailto=?, " .
261 2750
                                             "run_next=NULL " .
262
                                             "WHERE id=?");
263 3119
                        $sth->execute($day, $time, $mailto_type,
264
                                      $mailto_id, $sid);
265 2750
                    }
266
                }
267
            }
268
269
            # Check queries for changes
270 6889
            my $queries = Bugzilla::Whine::Query->match({ eventid => $eventid });
271
            for my $query (@$queries) {
272
                my $qid = $query->id;
273 2750
                if ($cgi->param("remove_query_$qid")) {
274
275
                    $sth = $dbh->prepare("SELECT whine_queries.id " .
276
                                         "FROM whine_queries " .
277
                                         "LEFT JOIN whine_events " .
278
                                         "ON whine_events.id = " .
279
                                         "whine_queries.eventid " .
280
                                         "WHERE whine_events.owner_userid=? " .
281
                                         "AND whine_queries.id =?");
282
                    $sth->execute($userid, $qid);
283
284
                    for (@{$sth->fetchall_arrayref}) {
285
                        $sth = $dbh->prepare("DELETE FROM whine_queries " .
286
                                             "WHERE id=?");
287
                        $sth->execute($_->[0]);
288
                    }
289
                }
290
                else {
291 3470
                    my $o_sort      = $cgi->param("orig_query_sort_$qid") || 0;
292
                    my $sort        = $cgi->param("query_sort_$qid") || 0;
293
                    my $o_queryname = $cgi->param("orig_query_name_$qid") || '';
294
                    my $queryname   = $cgi->param("query_name_$qid") || '';
295
                    my $o_title     = $cgi->param("orig_query_title_$qid") || '';
296
                    my $title       = $cgi->param("query_title_$qid") || '';
297 2750
                    my $o_onemailperbug =
298 3470
                            $cgi->param("orig_query_onemailperbug_$qid") || 0;
299 2750
                    my $onemailperbug   =
300 3470
                            $cgi->param("query_onemailperbug_$qid") ? 1 : 0;
301
302
                    if ( ($o_sort != $sort) ||
303 2750
                         ($o_queryname ne $queryname) ||
304 3470
                         ($o_onemailperbug != $onemailperbug) ||
305 2750
                         ($o_title ne $title) ){
306
307 3470
                        detaint_natural($sort);
308
                        trick_taint($queryname);
309
                        trick_taint($title);
310 2750
311
                        $sth = $dbh->prepare("UPDATE whine_queries " .
312
                                             "SET sortkey=?, " .
313
                                             "query_name=?, " .
314
                                             "title=?, " .
315
                                             "onemailperbug=? " .
316
                                             "WHERE id=?");
317
                        $sth->execute($sort, $queryname, $title,
318
                                      $onemailperbug, $qid);
319
                    }
320
                }
321
            }
322
        }
323
    }
324 4612
    delete_token($token);
325 2750
}
326
327
$vars->{'mail_others'} = $can_mail_others;
328
329
# Return the appropriate HTTP response headers.
330
print $cgi->header();
331
332
# Get events again, to cover any updates that were made
333
$events = get_events($userid);
334
335
# Here is the data layout as sent to the template:
336
#
337
#   events
338
#       event_id #
339
#           schedule
340
#               day
341
#               time
342
#               mailto
343
#           queries
344
#               name
345
#               title
346
#               sort
347
#
348
# build the whine list by event id
349
for my $event_id (keys %{$events}) {
350
    $events->{$event_id}->{'schedule'} = [];
351
    $events->{$event_id}->{'queries'} = [];
352
353
    # schedules
354 6809
    my $schedules = Bugzilla::Whine::Schedule->match({ eventid => $event_id });
355
    foreach my $schedule (@$schedules) {
356
        my $mailto_type = $schedule->mailto_is_group ? MAILTO_GROUP 
357
                                                     : MAILTO_USER;
358 3119
        my $mailto = '';
359
        if ($mailto_type == MAILTO_USER) {
360 6809
            $mailto = $schedule->mailto->login;
361 3119
        }
362
        elsif ($mailto_type == MAILTO_GROUP) {
363 6809
            $mailto = $schedule->mailto->name;
364 3119
        }
365 6809
366 6889
        push @{$events->{$event_id}->{'schedule'}},
367
             {
368
                 'day'         => $schedule->run_day,
369
                 'time'        => $schedule->run_time,
370
                 'mailto_type' => $mailto_type,
371
                 'mailto'      => $mailto,
372
                 'id'          => $schedule->id,
373
             };
374 2750
    }
375
376
    # queries
377 6889
    my $queries = Bugzilla::Whine::Query->match({ eventid => $event_id });
378
    for my $query (@$queries) {
379
        push @{$events->{$event_id}->{'queries'}}, 
380
             {
381
                 'name'          => $query->name,
382
                 'title'         => $query->title,
383
                 'sort'          => $query->sortkey,
384
                 'id'            => $query->id,
385
                 'onemailperbug' => $query->one_email_per_bug,
386
             };
387 2750
    }
388
}
389
390
$vars->{'events'} = $events;
391
392
# get the available queries
393
$sth = $dbh->prepare("SELECT name FROM namedqueries WHERE userid=?");
394
$sth->execute($userid);
395
396
$vars->{'available_queries'} = [];
397 3119
while (my ($query) = $sth->fetchrow_array) {
398
    push @{$vars->{'available_queries'}}, $query;
399 2750
}
400 4612
$vars->{'token'} = issue_session_token('edit_whine');
401 6201
$vars->{'local_timezone'} = Bugzilla->local_timezone->short_name_for_datetime(DateTime->now());
402 2750
403
$template->process("whine/schedule.html.tmpl", $vars)
404
  || ThrowTemplateError($template->error());
405
406 7270
# get_events takes a userid and returns a hash of
407
# Bugzilla::Whine objects keyed by event ID.
408 2750
sub get_events {
409
    my $userid = shift;
410 7270
    my $event_rows = Bugzilla::Whine->match({ owner_userid => $userid });
411
    my %events = map { $_->{id} => $_ } @$event_rows;
412 2750
413 7270
    return \%events;
414 2750
}
415

Loggerhead 1.18.1 is a web-based interface for Bazaar branches