bugzilla-4intranet/editwhines.cgi

358 lines
13 KiB
Perl
Executable File

#!/usr/bin/perl -wT
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Erik Stambaugh <erik@dasbistro.com>
#
use strict;
use lib qw(. lib);
use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Util;
use Bugzilla::Error;
use Bugzilla::User;
use Bugzilla::Group;
use Bugzilla::Token;
use Bugzilla::Whine::Schedule;
use Bugzilla::Whine::Query;
# require the user to have logged in
my $user = Bugzilla->login(LOGIN_REQUIRED);
my $ARGS = Bugzilla->input_params;
my $template = Bugzilla->template;
my $vars = {};
my $dbh = Bugzilla->dbh;
my $userid = $user->id;
my $token = $ARGS->{token};
# $events is a hash ref, keyed by event id, that stores the active user's
# events. It starts off with:
# 'subject' - the subject line for the email message
# 'body' - the text to be sent at the top of the message
#
# Eventually, it winds up with:
# 'queries' - array ref containing hashes of:
# 'name' - the name of the saved query
# 'title' - The title line for the search results table
# 'sort' - Numeric sort ID
# 'id' - row ID for the query entry
# 'onemailperbug' - whether a single message must be sent for each
# result.
# 'schedule' - array ref containing hashes of:
# 'day' - Day or range of days this schedule will be run
# 'time' - time or interval to run
# 'mailto_type' - MAILTO_USER or MAILTO_GROUP
# 'mailto' - person/group who will receive the results
# 'id' - row ID for the schedule
my $events = get_events($userid);
# First see if this user may use whines
$user->in_group('bz_canusewhines') || ThrowUserError("auth_failure", {
group => "bz_canusewhines",
action => "schedule",
object => "reports",
});
# May this user send mail to other users?
my $can_mail_others = Bugzilla->user->in_group('bz_canusewhineatothers');
# If the form was submitted, we need to look for what needs to be added or
# removed, then what was altered.
if ($ARGS->{update})
{
check_token_data($token, 'edit_whine');
if ($ARGS->{add_event})
{
# we create a new event
$dbh->do("INSERT INTO whine_events (owner_userid) VALUES (?)", undef, $userid);
}
else
{
for my $eventid (keys %{$events})
{
# delete an entire event
if ($ARGS->{"remove_event_$eventid"})
{
# We need to make sure these belong to the same user,
# otherwise we could simply delete whatever matched that ID.
$dbh->do("DELETE FROM whine_events WHERE id=? AND owner_userid=?", undef, $eventid, $userid);
}
else
{
# check the subject, body and mailifnobugs for changes
my $subject = $ARGS->{"event_${eventid}_subject"} || '';
my $body = $ARGS->{"event_${eventid}_body"} || '';
my $mailifnobugs = $ARGS->{"event_${eventid}_mailifnobugs"} ? 1 : 0;
trick_taint($subject) if $subject;
trick_taint($body) if $body;
if ($subject ne $events->{$eventid}->{subject} ||
$mailifnobugs != $events->{$eventid}->{mailifnobugs} ||
$body ne $events->{$eventid}->{body})
{
$dbh->do(
"UPDATE whine_events SET subject=?, body=?, mailifnobugs=? WHERE id=?",
undef, $subject, $body, $mailifnobugs, $eventid
);
}
# add a schedule
if ($ARGS->{"add_schedule_$eventid"})
{
# the schedule table must be locked before altering
$dbh->do(
"INSERT INTO whine_schedules (eventid, mailto_type, mailto, " .
"run_day, run_time) VALUES (?, ?, ?, 'Sun', 2)",
undef, $eventid, MAILTO_USER, $userid
);
}
# add a query
elsif ($ARGS->{"add_query_$eventid"})
{
$dbh->do("INSERT INTO whine_queries (eventid) VALUES (?)", undef, $eventid);
}
}
# now check all of the schedules and queries to see if they need
# to be altered or deleted
# Check schedules for changes
my $schedules = Bugzilla::Whine::Schedule->match({ eventid => $eventid });
my @scheduleids = ();
foreach my $schedule (@$schedules)
{
push @scheduleids, $schedule->id;
}
# we need to double-check all of the user IDs in mailto to make
# sure they exist
my $arglist = {}; # args for match_field
for my $sid (@scheduleids)
{
if ($ARGS->{"mailto_type_$sid"} == MAILTO_USER)
{
$arglist->{"mailto_$sid"} = { type => 'single' };
}
}
if (scalar %{$arglist})
{
Bugzilla::User::match_field($arglist);
}
for my $sid (@scheduleids)
{
if ($ARGS->{"remove_schedule_$sid"})
{
# having the assignee id in here is a security failsafe
$dbh->do(
"DELETE FROM whine_schedules WHERE id=?".
" AND (SELECT owner_userid FROM whine_events WHERE whine_events.id=eventid)=?",
undef, $sid, $userid
);
}
else
{
my $o_day = $ARGS->{"orig_day_$sid"} || '';
my $day = $ARGS->{"day_$sid"} || '';
my $o_time = $ARGS->{"orig_time_$sid"} || 0;
my $time = $ARGS->{"time_$sid"} || 0;
my $o_mailto = $ARGS->{"orig_mailto_$sid"} || '';
my $mailto = $ARGS->{"mailto_$sid"} || '';
my $o_mailto_type = $ARGS->{"orig_mailto_type_$sid"} || 0;
my $mailto_type = $ARGS->{"mailto_type_$sid"} || 0;
my $mailto_id = $userid;
# get an id for the mailto address
if ($can_mail_others && $mailto)
{
if ($mailto_type == MAILTO_USER)
{
$mailto_id = Bugzilla::User::login_to_id($mailto);
}
elsif ($mailto_type == MAILTO_GROUP)
{
# The group name is used in a placeholder.
trick_taint($mailto);
$mailto_id = Bugzilla::Group::ValidateGroupName($mailto, ($user))
|| ThrowUserError('invalid_group_name', { name => $mailto });
}
else
{
# bad value, so it will just mail to the whine
# owner. $mailto_id was already set above.
$mailto_type = MAILTO_USER;
}
}
detaint_natural($mailto_type);
if ($o_day ne $day || $o_time ne $time ||
$o_mailto ne $mailto || $o_mailto_type != $mailto_type)
{
trick_taint($day);
trick_taint($time);
# the schedule table must be locked
$dbh->do(
"UPDATE whine_schedules SET run_day=?, run_time=?,".
" mailto_type=?, mailto=?, run_next=NULL WHERE id=?",
undef, $day, $time, $mailto_type, $mailto_id, $sid
);
}
}
}
# Check queries for changes
my $queries = Bugzilla::Whine::Query->match({ eventid => $eventid });
for my $query (@$queries)
{
my $qid = $query->id;
if ($ARGS->{"remove_query_$qid"})
{
$dbh->do(
"DELETE FROM whine_queries WHERE id=?".
" AND (SELECT owner_userid FROM whine_events WHERE whine_events.id=eventid)=?",
undef, $qid, $userid
);
}
else
{
my $o_sort = $ARGS->{"orig_query_sort_$qid"} || 0;
my $sort = $ARGS->{"query_sort_$qid"} || 0;
my $o_queryname = $ARGS->{"orig_query_name_$qid"} || '';
my $queryname = $ARGS->{"query_name_$qid"} || '';
my $o_title = $ARGS->{"orig_query_title_$qid"} || '';
my $title = $ARGS->{"query_title_$qid"} || '';
my $o_onemailperbug = $ARGS->{"orig_query_onemailperbug_$qid"} || 0;
my $onemailperbug = $ARGS->{"query_onemailperbug_$qid"} ? 1 : 0;
my $isreport = 0;
if ($o_sort != $sort || $o_queryname ne $queryname ||
$o_onemailperbug != $onemailperbug || $o_title ne $title)
{
detaint_natural($sort);
trick_taint($queryname);
trick_taint($title);
if ($queryname =~ /^([01])-(.*)$/s)
{
($isreport, $queryname) = ($1, $2);
}
$dbh->do(
"UPDATE whine_queries SET sortkey=?, query_name=?, title=?, onemailperbug=?, isreport=? WHERE id=?",
undef, $sort, $queryname, $title, $onemailperbug, $isreport, $qid
);
}
}
}
}
}
delete_token($token);
}
$vars->{mail_others} = $can_mail_others;
# Get events again, to cover any updates that were made
$events = get_events($userid);
# Here is the data layout as sent to the template:
#
# events
# event_id #
# schedule
# day
# time
# mailto
# queries
# name
# title
# sort
#
# build the whine list by event id
for my $event_id (keys %{$events})
{
$events->{$event_id}->{schedule} = [];
$events->{$event_id}->{queries} = [];
# schedules
my $schedules = Bugzilla::Whine::Schedule->match({ eventid => $event_id });
foreach my $schedule (@$schedules)
{
my $mailto_type = $schedule->mailto_is_group ? MAILTO_GROUP : MAILTO_USER;
my $mailto = '';
if ($mailto_type == MAILTO_USER)
{
$mailto = $schedule->mailto && $schedule->mailto->login;
}
elsif ($mailto_type == MAILTO_GROUP)
{
$mailto = $schedule->mailto && $schedule->mailto->name;
}
push @{$events->{$event_id}->{schedule}}, {
day => $schedule->run_day,
time => $schedule->run_time,
mailto_type => $mailto_type,
mailto => $mailto,
id => $schedule->id,
};
}
# queries
my $queries = Bugzilla::Whine::Query->match({ eventid => $event_id });
for my $query (@$queries)
{
push @{$events->{$event_id}->{queries}}, {
name => $query->name,
title => $query->title,
sort => $query->sortkey,
id => $query->id,
onemailperbug => $query->one_email_per_bug,
isreport => $query->isreport,
};
}
}
$vars->{events} = $events;
# get the available queries
$vars->{available_queries} = $dbh->selectcol_arrayref("SELECT name FROM namedqueries WHERE userid=? ORDER BY name", undef, $userid) || [];
$vars->{available_reports} = $dbh->selectcol_arrayref("SELECT name FROM reports WHERE user_id=? ORDER BY name", undef, $userid) || [];
$vars->{token} = issue_session_token('edit_whine');
$vars->{local_timezone} = Bugzilla->local_timezone->short_name_for_datetime(DateTime->now());
$template->process("whine/schedule.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
exit;
# get_events takes a userid and returns a hash, keyed by event ID, containing
# the subject and body of each event that user owns
sub get_events
{
my $userid = shift;
return Bugzilla->dbh->selectall_hashref(
"SELECT DISTINCT id, subject, body, mailifnobugs FROM whine_events WHERE owner_userid=?",
'id', undef, $userid
);
}