From f9214d522c9dabc0096573e553b946c492a65230 Mon Sep 17 00:00:00 2001 From: "gerv%gerv.net" <> Date: Mon, 30 Aug 2004 04:29:34 +0000 Subject: Bug 225687 - add group controls to charts, along with various other cleanups. Patch by gerv; r=joel, a=justdave. --- Bugzilla/Chart.pm | 48 +++++++++++++++---------- Bugzilla/Series.pm | 104 ++++++++++++++++++++--------------------------------- 2 files changed, 68 insertions(+), 84 deletions(-) (limited to 'Bugzilla') diff --git a/Bugzilla/Chart.pm b/Bugzilla/Chart.pm index 42827750f..90c1ad16f 100644 --- a/Bugzilla/Chart.pm +++ b/Bugzilla/Chart.pm @@ -71,8 +71,8 @@ sub init { foreach my $series_id ($cgi->param($param)) { detaint_natural($series_id) || &::ThrowCodeError("invalid_series_id"); - push(@{$self->{'lines'}[$1]}, - new Bugzilla::Series($series_id)); + my $series = new Bugzilla::Series($series_id); + push(@{$self->{'lines'}[$1]}, $series) if $series; } } @@ -130,8 +130,10 @@ sub add { # for inventing something sensible. foreach my $series_id (@series_ids) { my $series = new Bugzilla::Series($series_id); - push(@{$self->{'lines'}}, [$series]); - push(@{$self->{'labels'}}, ""); + if ($series) { + push(@{$self->{'lines'}}, [$series]); + push(@{$self->{'labels'}}, ""); + } } } @@ -199,6 +201,8 @@ sub readData { my $self = shift; my @data; + # Note: you get a bad image if getSeriesIDs returns nothing + # We need to handle errors better. my $series_ids = join(",", $self->getSeriesIDs()); # Work out the date boundaries for our data. @@ -206,7 +210,8 @@ sub readData { # The date used is the one given if it's in a sensible range; otherwise, # it's the earliest or latest date in the database as appropriate. - my $datefrom = $dbh->selectrow_array("SELECT MIN(date) FROM series_data " . + my $datefrom = $dbh->selectrow_array("SELECT MIN(series_date) " . + "FROM series_data " . "WHERE series_id IN ($series_ids)"); $datefrom = &::str2time($datefrom); @@ -214,7 +219,8 @@ sub readData { $datefrom = $self->{'datefrom'}; } - my $dateto = $dbh->selectrow_array("SELECT MAX(date) FROM series_data " . + my $dateto = $dbh->selectrow_array("SELECT MAX(series_date) " . + "FROM series_data " . "WHERE series_id IN ($series_ids)"); $dateto = &::str2time($dateto); @@ -223,12 +229,13 @@ sub readData { } # Prepare the query which retrieves the data for each series - my $query = "SELECT TO_DAYS(date) - TO_DAYS(FROM_UNIXTIME($datefrom)), " . - "value FROM series_data " . + my $query = "SELECT TO_DAYS(series_date) - " . + " TO_DAYS(FROM_UNIXTIME($datefrom)), " . + "series_value FROM series_data " . "WHERE series_id = ? " . - "AND date >= FROM_UNIXTIME($datefrom)"; + "AND series_date >= FROM_UNIXTIME($datefrom)"; if ($dateto) { - $query .= " AND date <= FROM_UNIXTIME($dateto)"; + $query .= " AND series_date <= FROM_UNIXTIME($dateto)"; } my $sth = $dbh->prepare($query); @@ -296,19 +303,24 @@ sub getSeriesIDs { sub getVisibleSeries { my %cats; + # List of groups the user is in; use -1 to make sure it's not empty. + my $grouplist = join(", ", (-1, values(%{Bugzilla->user->groups}))); + # Get all visible series my $dbh = Bugzilla->dbh; my $serieses = $dbh->selectall_arrayref("SELECT cc1.name, cc2.name, " . "series.name, series.series_id " . "FROM series " . - "LEFT JOIN series_categories AS cc1 " . - " ON series.category = cc1.category_id " . - "LEFT JOIN series_categories AS cc2 " . - " ON series.subcategory = cc2.category_id " . - "LEFT JOIN user_series_map AS ucm " . - " ON series.series_id = ucm.series_id " . - "WHERE ucm.user_id = 0 OR ucm.user_id = $::userid"); - + "INNER JOIN series_categories AS cc1 " . + " ON series.category = cc1.id " . + "INNER JOIN series_categories AS cc2 " . + " ON series.subcategory = cc2.id " . + "LEFT JOIN category_group_map AS cgm " . + " ON series.category = cgm.category_id " . + " AND cgm.group_id NOT IN($grouplist) " . + "WHERE creator = " . Bugzilla->user->id . " OR " . + " cgm.category_id IS NULL " . + "GROUP BY series_id"); foreach my $series (@$serieses) { my ($cat, $subcat, $name, $series_id) = @$series; $cats{$cat}{$subcat}{$name} = $series_id; diff --git a/Bugzilla/Series.pm b/Bugzilla/Series.pm index 4d01a71ca..a4bd6654f 100644 --- a/Bugzilla/Series.pm +++ b/Bugzilla/Series.pm @@ -47,6 +47,11 @@ sub new { my $arg_count = scalar(@_); + # new() can return undef if you pass in a series_id and the user doesn't + # have sufficient permissions. If you create a new series in this way, + # you need to check for an undef return, and act appropriately. + my $retval = $self; + # There are three ways of creating Series objects. Two (CGI and Parameters) # are for use when creating a new series. One (Database) is for retrieving # information on existing series. @@ -60,7 +65,7 @@ sub new { else { # We've been given a series_id, which should represent an existing # Series. - $self->initFromDatabase($_[0]); + $retval = $self->initFromDatabase($_[0]); } } elsif ($arg_count >= 6 && $arg_count <= 8) { @@ -73,7 +78,7 @@ sub new { die("Bad parameters passed in - invalid number of args: $arg_count"); } - return $self; + return $retval; } sub initFromDatabase { @@ -86,23 +91,29 @@ sub initFromDatabase { my $dbh = Bugzilla->dbh; my @series = $dbh->selectrow_array("SELECT series.series_id, cc1.name, " . "cc2.name, series.name, series.creator, series.frequency, " . - "series.query " . + "series.query, series.public " . "FROM series " . "LEFT JOIN series_categories AS cc1 " . - " ON series.category = cc1.category_id " . + " ON series.category = cc1.id " . "LEFT JOIN series_categories AS cc2 " . - " ON series.subcategory = cc2.category_id " . - "WHERE series.series_id = $series_id"); + " ON series.subcategory = cc2.id " . + "LEFT JOIN category_group_map AS cgm " . + " ON series.category = cgm.category_id " . + "LEFT JOIN user_group_map AS ugm " . + " ON cgm.group_id = ugm.group_id " . + " AND ugm.user_id = " . Bugzilla->user->id . + " AND isbless = 0 " . + "WHERE series.series_id = $series_id AND " . + "(public = 1 OR creator = " . Bugzilla->user->id . " OR " . + "(ugm.group_id IS NOT NULL)) " . + "GROUP BY series_id"); if (@series) { - # Note that we calculate $self->{'public'} ourselves instead of passing - # it as the last parameter in @series; this is because isSubscribed() - # requires the rest of the object to be set up correctly. $self->initFromParameters(@series); - $self->{'public'} = $self->isSubscribed(PUBLIC_USER_ID); + return $self; } else { - &::ThrowCodeError("invalid_series_id", { 'series_id' => $series_id }); + return undef; } } @@ -146,16 +157,20 @@ sub initFromCGI { $self->{'query'} = $cgi->canonicalise_query("format", "ctype", "action", "category", "subcategory", "name", "frequency", "public", "query_format"); + trick_taint($self->{'query'}); - $self->{'public'} = $cgi->param('public') ? 1 : 0; + $self->{'public'} = $cgi->param('public') ? 1 : 0; + + # Change 'admin' here and in series.html.tmpl, or remove the check + # completely, if you want to change who can make series public. + $self->{'public'} = 0 unless &::UserInGroup('admin'); } sub writeToDatabase { my $self = shift; my $dbh = Bugzilla->dbh; - $dbh->do("LOCK TABLES series_categories WRITE, series WRITE, " . - "user_series_map WRITE"); + $dbh->do("LOCK TABLES series_categories WRITE, series WRITE"); my $category_id = getCategoryID($self->{'category'}); my $subcategory_id = getCategoryID($self->{'subcategory'}); @@ -173,37 +188,28 @@ sub writeToDatabase { my $dbh = Bugzilla->dbh; $dbh->do("UPDATE series SET " . "category = ?, subcategory = ?," . - "name = ?, frequency = ? " . + "name = ?, frequency = ?, public = ? " . "WHERE series_id = ?", undef, $category_id, $subcategory_id, $self->{'name'}, - $self->{'frequency'}, $self->{'series_id'}); + $self->{'frequency'}, $self->{'public'}, + $self->{'series_id'}); } else { # Insert the new series into the series table $dbh->do("INSERT INTO series (creator, category, subcategory, " . - "name, frequency, query) VALUES ($self->{'creator'}, " . + "name, frequency, query, public) VALUES " . + "($self->{'creator'}, " . "$category_id, $subcategory_id, " . $dbh->quote($self->{'name'}) . ", $self->{'frequency'}," . - $dbh->quote($self->{'query'}) . ")"); + $dbh->quote($self->{'query'}) . ", $self->{'public'})"); # Retrieve series_id $self->{'series_id'} = $dbh->selectrow_array("SELECT MAX(series_id) " . "FROM series"); $self->{'series_id'} || &::ThrowCodeError("missing_series_id", { 'series' => $self }); - - # Subscribe creator to the newly-created series. - $self->subscribe($self->{'creator'}); } - # Update publicness by changing subscription - if ($self->{'public'}) { - $self->subscribe(PUBLIC_USER_ID); - } - else { - $self->unsubscribe(PUBLIC_USER_ID); - } - $dbh->do("UNLOCK TABLES"); } @@ -236,51 +242,17 @@ sub getCategoryID { # We are quoting this to put it in the DB, so we can remove taint trick_taint($category); - $category_id = $dbh->selectrow_array("SELECT category_id " . + $category_id = $dbh->selectrow_array("SELECT id " . "from series_categories " . "WHERE name =" . $dbh->quote($category)); - last if $category_id; + + last if defined($category_id); $dbh->do("INSERT INTO series_categories (name) " . "VALUES (" . $dbh->quote($category) . ")"); } return $category_id; -} - -sub subscribe { - my $self = shift; - my $userid = shift; - - if (!$self->isSubscribed($userid)) { - # Subscribe current user to series_id - my $dbh = Bugzilla->dbh; - $dbh->do("INSERT INTO user_series_map " . - "VALUES($userid, $self->{'series_id'})"); - } -} - -sub unsubscribe { - my $self = shift; - my $userid = shift; - - if ($self->isSubscribed($userid)) { - # Remove current user's subscription to series_id - my $dbh = Bugzilla->dbh; - $dbh->do("DELETE FROM user_series_map " . - "WHERE user_id = $userid AND series_id = $self->{'series_id'}"); - } -} - -sub isSubscribed { - my $self = shift; - my $userid = shift; - - my $dbh = Bugzilla->dbh; - my $issubscribed = $dbh->selectrow_array("SELECT 1 FROM user_series_map " . - "WHERE user_id = $userid " . - "AND series_id = $self->{'series_id'}"); - return $issubscribed; } 1; -- cgit v1.2.3-24-g4f1b