Commit 1d057f02 authored by bbaetz%acm.org's avatar bbaetz%acm.org

Bug 180635 - Enhance Bugzilla::User to store additional information

r=myk,jake
parent 3a843833
...@@ -77,17 +77,15 @@ sub login { ...@@ -77,17 +77,15 @@ sub login {
# Compat stuff # Compat stuff
$::userid = $userid; $::userid = $userid;
&::ConfirmGroup($userid);
# Evil compat hack. The cookie stores the id now, not the name, but # Evil compat hack. The cookie stores the id now, not the name, but
# old code still looks at this to get the current user's email # old code still looks at this to get the current user's email
# so it needs to be set. # so it needs to be set.
$::COOKIE{'Bugzilla_login'} = $_user->{email}; $::COOKIE{'Bugzilla_login'} = $_user->login;
$::vars->{'user'} = &::GetUserInfo($userid);
} else { } else {
# Old compat stuff # Old compat stuff
undef $_user;
$::userid = 0; $::userid = 0;
delete $::COOKIE{'Bugzilla_login'}; delete $::COOKIE{'Bugzilla_login'};
delete $::COOKIE{'Bugzilla_logincookie'}; delete $::COOKIE{'Bugzilla_logincookie'};
...@@ -97,7 +95,12 @@ sub login { ...@@ -97,7 +95,12 @@ sub login {
# - use Bugzilla->user instead! # - use Bugzilla->user instead!
} }
return $userid || 0; return $_user;
}
sub logout {
undef $_user;
$::userid = 0;
} }
my $_dbh; my $_dbh;
...@@ -257,8 +260,16 @@ or if the login code has not yet been run. ...@@ -257,8 +260,16 @@ or if the login code has not yet been run.
=item C<login> =item C<login>
Logs in a user, returning the userid, or C<0> if there is no logged in user. Logs in a user, returning a C<Bugzilla::User> object, or C<undef> if there is
See L<Bugzilla::Auth>. no logged in user. See L<Bugzilla::Auth|Bugzilla::Auth> and
L<Bugzilla::User|Bugzilla::User>.
=item C<logout>
Logs out the current user. For the moment, this will just cause calls to
C<user> to return C<undef>. Eventually this will handle deleting cookies from
the browser and values from the database, which is currently all handled
by C<relogin.cgi>.
=item C<dbh> =item C<dbh>
......
...@@ -111,14 +111,6 @@ sub Send($;$) { ...@@ -111,14 +111,6 @@ sub Send($;$) {
# require abuse we do. # require abuse we do.
GetVersionTable(); GetVersionTable();
# Since any email recipients must be rederived if the user has not
# been rederived since the most recent group change, figure out when that
# is once and determine the need to rederive users using the same DB
# access that gets the user's email address each time a person is
# processed.
SendSQL("SELECT MAX(last_changed) FROM groups");
($last_changed) = FetchSQLData();
# Make sure to clean up _all_ package vars here. Yuck... # Make sure to clean up _all_ package vars here. Yuck...
$nametoexclude = $recipients->{'changer'} || ""; $nametoexclude = $recipients->{'changer'} || "";
@{$force{'CClist'}} = (exists $recipients->{'cc'} && @{$force{'CClist'}} = (exists $recipients->{'cc'} &&
...@@ -710,19 +702,13 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) { ...@@ -710,19 +702,13 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) {
return; return;
} }
# This routine should really get passed a userid
SendSQL("SELECT userid, (refreshed_when > " . SqlQuote($last_changed) . # This rederives groups as a side effect
") FROM profiles WHERE login_name = " . SqlQuote($person)); my $user = Bugzilla::User->new_from_login($person);
my ($userid, $current) = (FetchSQLData()); my $userid = $user->id;
$seen{$person} = 1; $seen{$person} = 1;
detaint_natural($userid);
if (!$current) {
DeriveGroup($userid);
}
# if this person doesn't have permission to see info on this bug, # if this person doesn't have permission to see info on this bug,
# return. # return.
# #
...@@ -732,12 +718,11 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) { ...@@ -732,12 +718,11 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) {
# quietly disappear from their radar. # quietly disappear from their radar.
# #
return unless CanSeeBug($id, $userid); return unless CanSeeBug($id, $userid);
# Drop any non-insiders if the comment is private # Drop any non-insiders if the comment is private
return if (Param("insidergroup") && return if (Param("insidergroup") &&
($anyprivate != 0) && ($anyprivate != 0) &&
(!UserInGroup(Param("insidergroup"), $userid))); (!$user->groups->{Param("insidergroup")}));
# We shouldn't send changedmail if this is a dependency mail, and any of # We shouldn't send changedmail if this is a dependency mail, and any of
# the depending bugs is not visible to the user. # the depending bugs is not visible to the user.
...@@ -761,8 +746,8 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) { ...@@ -761,8 +746,8 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) {
} }
# Don't send estimated_time if user not in the group, or not enabled # Don't send estimated_time if user not in the group, or not enabled
if ($f ne 'estimated_time' || if ($f ne 'estimated_time' ||
UserInGroup(Param('timetrackinggroup'), $userid)) { $user->groups->{Param('timetrackinggroup')}) {
my $desc = $fielddescription{$f}; my $desc = $fielddescription{$f};
$head .= FormatDouble($desc, $value); $head .= FormatDouble($desc, $value);
} }
...@@ -781,7 +766,7 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) { ...@@ -781,7 +766,7 @@ sub NewProcessOnePerson ($$$$$$$$$$$$$) {
($diff->{'fieldname'} eq 'estimated_time' || ($diff->{'fieldname'} eq 'estimated_time' ||
$diff->{'fieldname'} eq 'remaining_time' || $diff->{'fieldname'} eq 'remaining_time' ||
$diff->{'fieldname'} eq 'work_time')) { $diff->{'fieldname'} eq 'work_time')) {
if (UserInGroup(Param("timetrackinggroup"), $userid)) { if ($user->groups->{Param("timetrackinggroup")}) {
$add_diff = 1; $add_diff = 1;
} }
} else { } else {
......
...@@ -34,9 +34,6 @@ sub ThrowUserError { ...@@ -34,9 +34,6 @@ sub ThrowUserError {
$vars->{error} = $error; $vars->{error} = $error;
# Need to do this until User.pm goes in, so that the footer is correct
$vars->{user} = $::vars->{user};
Bugzilla->dbh->do("UNLOCK TABLES") if $unlock_tables; Bugzilla->dbh->do("UNLOCK TABLES") if $unlock_tables;
print Bugzilla->cgi->header(); print Bugzilla->cgi->header();
......
...@@ -177,18 +177,14 @@ sub validate { ...@@ -177,18 +177,14 @@ sub validate {
if ($requestee_email ne $flag->{'requestee'}->{'email'}) { if ($requestee_email ne $flag->{'requestee'}->{'email'}) {
# We know the requestee exists because we ran # We know the requestee exists because we ran
# Bugzilla::User::match_field before getting here. # Bugzilla::User::match_field before getting here.
# ConfirmGroup makes sure their group settings my $requestee = Bugzilla::User->new_from_login($requestee_email);
# are up-to-date or calls DeriveGroups to update them.
my $requestee_id = &::DBname_to_id($requestee_email);
&::ConfirmGroup($requestee_id);
# Throw an error if the user can't see the bug. # Throw an error if the user can't see the bug.
if (!&::CanSeeBug($bug_id, $requestee_id)) if (!&::CanSeeBug($bug_id, $requestee->id))
{ {
ThrowUserError("flag_requestee_unauthorized", ThrowUserError("flag_requestee_unauthorized",
{ flag_type => $flag->{'type'}, { flag_type => $flag->{'type'},
requestee => requestee => $requestee,
new Bugzilla::User($requestee_id),
bug_id => $bug_id, bug_id => $bug_id,
attach_id => attach_id =>
$flag->{target}->{attachment}->{id} }); $flag->{target}->{attachment}->{id} });
...@@ -198,13 +194,12 @@ sub validate { ...@@ -198,13 +194,12 @@ sub validate {
# the requestee isn't in the group of insiders who can see it. # the requestee isn't in the group of insiders who can see it.
if ($flag->{target}->{attachment}->{exists} if ($flag->{target}->{attachment}->{exists}
&& $data->{'isprivate'} && $data->{'isprivate'}
&& &::Param("insidergroup") && Param("insidergroup")
&& !&::UserInGroup(&::Param("insidergroup"), $requestee_id)) && !$requestee->in_group(Param("insidergroup")))
{ {
ThrowUserError("flag_requestee_unauthorized_attachment", ThrowUserError("flag_requestee_unauthorized_attachment",
{ flag_type => $flag->{'type'}, { flag_type => $flag->{'type'},
requestee => requestee => $requestee,
new Bugzilla::User($requestee_id),
bug_id => $bug_id, bug_id => $bug_id,
attach_id => attach_id =>
$flag->{target}->{attachment}->{id} }); $flag->{target}->{attachment}->{id} });
...@@ -236,7 +231,7 @@ sub process { ...@@ -236,7 +231,7 @@ sub process {
my @old_summaries; my @old_summaries;
foreach my $flag (@$flags) { foreach my $flag (@$flags) {
my $summary = $flag->{'type'}->{'name'} . $flag->{'status'}; my $summary = $flag->{'type'}->{'name'} . $flag->{'status'};
$summary .= "($flag->{'requestee'}->{'email'})" if $flag->{'requestee'}; $summary .= "(" . $flag->{'requestee'}->login . ")" if $flag->{'requestee'};
push(@old_summaries, $summary); push(@old_summaries, $summary);
} }
...@@ -275,7 +270,7 @@ sub process { ...@@ -275,7 +270,7 @@ sub process {
my @new_summaries; my @new_summaries;
foreach my $flag (@$flags) { foreach my $flag (@$flags) {
my $summary = $flag->{'type'}->{'name'} . $flag->{'status'}; my $summary = $flag->{'type'}->{'name'} . $flag->{'status'};
$summary .= "($flag->{'requestee'}->{'email'})" if $flag->{'requestee'}; $summary .= "(" . $flag->{'requestee'}->login . ")" if $flag->{'requestee'};
push(@new_summaries, $summary); push(@new_summaries, $summary);
} }
...@@ -307,7 +302,7 @@ sub create { ...@@ -307,7 +302,7 @@ sub create {
# Insert a record for the flag into the flags table. # Insert a record for the flag into the flags table.
my $attach_id = $flag->{'target'}->{'attachment'}->{'id'} || "NULL"; my $attach_id = $flag->{'target'}->{'attachment'}->{'id'} || "NULL";
my $requestee_id = $flag->{'requestee'} ? $flag->{'requestee'}->{'id'} : "NULL"; my $requestee_id = $flag->{'requestee'} ? $flag->{'requestee'}->id : "NULL";
&::SendSQL("INSERT INTO flags (id, type_id, &::SendSQL("INSERT INTO flags (id, type_id,
bug_id, attach_id, bug_id, attach_id,
requestee_id, setter_id, status, requestee_id, setter_id, status,
...@@ -317,7 +312,7 @@ sub create { ...@@ -317,7 +312,7 @@ sub create {
$flag->{'target'}->{'bug'}->{'id'}, $flag->{'target'}->{'bug'}->{'id'},
$attach_id, $attach_id,
$requestee_id, $requestee_id,
$flag->{'setter'}->{'id'}, " . $flag->{'setter'}->id . ",
'$flag->{'status'}', '$flag->{'status'}',
$timestamp, $timestamp,
$timestamp)"); $timestamp)");
...@@ -380,7 +375,7 @@ sub modify { ...@@ -380,7 +375,7 @@ sub modify {
# the flag isn't specifically requestable # the flag isn't specifically requestable
|| $status ne "?" # or the flag isn't being requested || $status ne "?" # or the flag isn't being requested
|| ($flag->{'requestee'} # or the requestee hasn't changed || ($flag->{'requestee'} # or the requestee hasn't changed
&& ($requestee_email eq $flag->{'requestee'}->{'email'}))); && ($requestee_email eq $flag->{'requestee'}->login)));
# Since the status is validated, we know it's safe, but it's still # Since the status is validated, we know it's safe, but it's still
# tainted, so we have to detaint it before using it in a query. # tainted, so we have to detaint it before using it in a query.
...@@ -568,14 +563,15 @@ sub notify { ...@@ -568,14 +563,15 @@ sub notify {
{ {
my @new_cc_list; my @new_cc_list;
foreach my $cc (split(/[, ]+/, $flag->{'type'}->{'cc_list'})) { foreach my $cc (split(/[, ]+/, $flag->{'type'}->{'cc_list'})) {
my $user_id = &::DBname_to_id($cc) || next; my $ccuser = Bugzilla::User->new_from_login($cc,
# re-derive permissions if necessary TABLES_ALREADY_LOCKED)
&::ConfirmGroup($user_id, TABLES_ALREADY_LOCKED); || next;
next if $flag->{'target'}->{'bug'}->{'restricted'} next if $flag->{'target'}->{'bug'}->{'restricted'}
&& !&::CanSeeBug($flag->{'target'}->{'bug'}->{'id'}, $user_id); && !&::CanSeeBug($flag->{'target'}->{'bug'}->{'id'}, $ccuser->id);
next if $flag->{'target'}->{'attachment'}->{'isprivate'} next if $flag->{'target'}->{'attachment'}->{'isprivate'}
&& Param("insidergroup") && Param("insidergroup")
&& !&::UserInGroup(Param("insidergroup"), $user_id); && !$ccuser->in_group(Param("insidergroup"));
push(@new_cc_list, $cc); push(@new_cc_list, $cc);
} }
$flag->{'type'}->{'cc_list'} = join(", ", @new_cc_list); $flag->{'type'}->{'cc_list'} = join(", ", @new_cc_list);
...@@ -646,7 +642,7 @@ sub perlify_record { ...@@ -646,7 +642,7 @@ sub perlify_record {
id => $id , id => $id ,
type => Bugzilla::FlagType::get($type_id) , type => Bugzilla::FlagType::get($type_id) ,
target => GetTarget($bug_id, $attach_id) , target => GetTarget($bug_id, $attach_id) ,
requestee => new Bugzilla::User($requestee_id) , requestee => $requestee_id ? new Bugzilla::User($requestee_id) : undef,
setter => new Bugzilla::User($setter_id) , setter => new Bugzilla::User($setter_id) ,
status => $status , status => $status ,
}; };
......
...@@ -219,20 +219,17 @@ sub validate { ...@@ -219,20 +219,17 @@ sub validate {
&& trim($data->{"requestee_type-$id"})) && trim($data->{"requestee_type-$id"}))
{ {
my $requestee_email = trim($data->{"requestee_type-$id"}); my $requestee_email = trim($data->{"requestee_type-$id"});
my $requestee_id = &::DBname_to_id($requestee_email);
# We know the requestee exists because we ran # We know the requestee exists because we ran
# Bugzilla::User::match_field before getting here. # Bugzilla::User::match_field before getting here.
# ConfirmGroup makes sure their group settings my $requestee = Bugzilla::User->new_from_login($requestee_email);
# are up-to-date or calls DeriveGroups to update them.
&::ConfirmGroup($requestee_id);
# Throw an error if the user can't see the bug. # Throw an error if the user can't see the bug.
if (!&::CanSeeBug($bug_id, $requestee_id)) if (!&::CanSeeBug($bug_id, $requestee->id))
{ {
ThrowUserError("flag_requestee_unauthorized", ThrowUserError("flag_requestee_unauthorized",
{ flag_type => $flag_type, { flag_type => $flag_type,
requestee => new Bugzilla::User($requestee_id), requestee => $requestee,
bug_id => $bug_id, bug_id => $bug_id,
attach_id => $attach_id }); attach_id => $attach_id });
} }
...@@ -240,13 +237,13 @@ sub validate { ...@@ -240,13 +237,13 @@ sub validate {
# Throw an error if the target is a private attachment and # Throw an error if the target is a private attachment and
# the requestee isn't in the group of insiders who can see it. # the requestee isn't in the group of insiders who can see it.
if ($attach_id if ($attach_id
&& &::Param("insidergroup") && Param("insidergroup")
&& $data->{'isprivate'} && $data->{'isprivate'}
&& !&::UserInGroup(&::Param("insidergroup"), $requestee_id)) && !$requestee->in_group(Param("insidergroup")))
{ {
ThrowUserError("flag_requestee_unauthorized_attachment", ThrowUserError("flag_requestee_unauthorized_attachment",
{ flag_type => $flag_type, { flag_type => $flag_type,
requestee => new Bugzilla::User($requestee_id), requestee => $requestee,
bug_id => $bug_id, bug_id => $bug_id,
attach_id => $attach_id }); attach_id => $attach_id });
} }
......
...@@ -926,28 +926,31 @@ sub init { ...@@ -926,28 +926,31 @@ sub init {
# Make sure we create a legal SQL query. # Make sure we create a legal SQL query.
@andlist = ("1 = 1") if !@andlist; @andlist = ("1 = 1") if !@andlist;
my $user = Bugzilla->user;
my $query = "SELECT " . join(', ', @fields) . my $query = "SELECT " . join(', ', @fields) .
" FROM $suppstring" . " FROM $suppstring" .
" LEFT JOIN bug_group_map " . " LEFT JOIN bug_group_map " .
" ON bug_group_map.bug_id = bugs.bug_id "; " ON bug_group_map.bug_id = bugs.bug_id ";
if (defined @{$::vars->{user}{groupids}} && @{$::vars->{user}{groupids}} > 0) { if ($user) {
$query .= " AND bug_group_map.group_id NOT IN (" . join(',', @{$::vars->{user}{groupids}}) . ") "; if (%{$user->groups}) {
} $query .= " AND bug_group_map.group_id NOT IN (" . join(',', values(%{$user->groups})) . ") ";
}
if ($::vars->{user}{userid}) { $query .= " LEFT JOIN cc ON cc.bug_id = bugs.bug_id AND cc.who = " . $user->id;
$query .= " LEFT JOIN cc ON cc.bug_id = bugs.bug_id AND cc.who = $::userid ";
} }
$query .= " WHERE " . join(' AND ', (@wherepart, @andlist)) . $query .= " WHERE " . join(' AND ', (@wherepart, @andlist)) .
" AND ((bug_group_map.group_id IS NULL)"; " AND ((bug_group_map.group_id IS NULL)";
if ($::vars->{user}{userid}) { if ($user) {
$query .= " OR (bugs.reporter_accessible = 1 AND bugs.reporter = $::userid) " . my $userid = $user->id;
$query .= " OR (bugs.reporter_accessible = 1 AND bugs.reporter = $userid) " .
" OR (bugs.cclist_accessible = 1 AND cc.who IS NOT NULL) " . " OR (bugs.cclist_accessible = 1 AND cc.who IS NOT NULL) " .
" OR (bugs.assigned_to = $::userid) "; " OR (bugs.assigned_to = $userid) ";
if (Param('useqacontact')) { if (Param('useqacontact')) {
$query .= "OR (bugs.qa_contact = $::userid) "; $query .= "OR (bugs.qa_contact = $userid) ";
} }
} }
......
...@@ -256,7 +256,10 @@ sub create { ...@@ -256,7 +256,10 @@ sub create {
# Generic linear search function # Generic linear search function
'lsearch' => \&Bugzilla::Util::lsearch, 'lsearch' => \&Bugzilla::Util::lsearch,
# UserInGroup - you probably want to cache this # Currently logged in user, if any
'user' => sub { return Bugzilla->user; },
# UserInGroup. Deprecated - use the user.* functions instead
'UserInGroup' => \&::UserInGroup, 'UserInGroup' => \&::UserInGroup,
# SendBugMail - sends mail about a bug, using Bugzilla::BugMail.pm # SendBugMail - sends mail about a bug, using Bugzilla::BugMail.pm
......
...@@ -202,53 +202,6 @@ sub quietly_check_login { ...@@ -202,53 +202,6 @@ sub quietly_check_login {
return Bugzilla->login($_[0] ? LOGIN_OPTIONAL : LOGIN_NORMAL); return Bugzilla->login($_[0] ? LOGIN_OPTIONAL : LOGIN_NORMAL);
} }
# Populate a hash with information about this user.
sub GetUserInfo {
my ($userid) = (@_);
my %user;
my @queries;
my %groups;
my @groupids;
# No info if not logged in
return \%user if ($userid == 0);
$user{'login'} = $::COOKIE{"Bugzilla_login"};
$user{'userid'} = $userid;
SendSQL("SELECT mybugslink, realname " .
"FROM profiles WHERE userid = $userid");
($user{'showmybugslink'}, $user{'realname'}) = FetchSQLData();
SendSQL("SELECT name, query, linkinfooter FROM namedqueries " .
"WHERE userid = $userid");
while (MoreSQLData()) {
my %query;
($query{'name'}, $query{'query'}, $query{'linkinfooter'}) =
FetchSQLData();
push(@queries, \%query);
}
$user{'queries'} = \@queries;
$user{'canblessany'} = UserCanBlessAnything();
SendSQL("SELECT DISTINCT id, name FROM groups, user_group_map " .
"WHERE groups.id = user_group_map.group_id " .
"AND user_id = $userid " .
"AND NOT isbless");
while (MoreSQLData()) {
my ($id, $name) = FetchSQLData();
push(@groupids,$id);
$groups{$name} = 1;
}
$user{'groups'} = \%groups;
$user{'groupids'} = \@groupids;
return \%user;
}
sub CheckEmailSyntax { sub CheckEmailSyntax {
my ($addr) = (@_); my ($addr) = (@_);
my $match = Param('emailregexp'); my $match = Param('emailregexp');
......
...@@ -693,11 +693,11 @@ sub update ...@@ -693,11 +693,11 @@ sub update
"flaginclusions AS i READ, flagexclusions AS e READ, " . "flaginclusions AS i READ, flagexclusions AS e READ, " .
# cc, bug_group_map, user_group_map, and groups are in here so we # cc, bug_group_map, user_group_map, and groups are in here so we
# can check the permissions of flag requestees and email addresses # can check the permissions of flag requestees and email addresses
# on the flag type cc: lists via the ConfirmGroup and CanSeeBug # on the flag type cc: lists via the CanSeeBug
# function calls in Flag::notify. group_group_map is in here in case # function call in Flag::notify. group_group_map is in here in case
# ConfirmGroup needs to call DeriveGroup. profiles and user_group_map # Bugzilla::User needs to rederive groups. profiles and
# would be READ locks instead of WRITE locks if it weren't for # user_group_map would be READ locks instead of WRITE locks if it
# DeriveGroup, which needs to write to those tables. # weren't for derive_groups, which needs to write to those tables.
"bugs READ, profiles WRITE, " . "bugs READ, profiles WRITE, " .
"cc READ, bug_group_map READ, user_group_map WRITE, " . "cc READ, bug_group_map READ, user_group_map WRITE, " .
"group_group_map READ, groups READ"); "group_group_map READ, groups READ");
......
...@@ -272,15 +272,9 @@ if ($::FORM{'cmdtype'} eq "dorem") { ...@@ -272,15 +272,9 @@ if ($::FORM{'cmdtype'} eq "dorem") {
my $userid = DBNameToIdAndCheck($::COOKIE{"Bugzilla_login"}); my $userid = DBNameToIdAndCheck($::COOKIE{"Bugzilla_login"});
my $qname = SqlQuote($::FORM{'namedcmd'}); my $qname = SqlQuote($::FORM{'namedcmd'});
SendSQL("DELETE FROM namedqueries WHERE userid = $userid AND name = $qname"); SendSQL("DELETE FROM namedqueries WHERE userid = $userid AND name = $qname");
# Now remove this query from the footer
my $count = 0; # Now reset the cached queries
foreach my $q (@{$::vars->{'user'}{'queries'}}) { Bugzilla->user->flush_queries_cache();
if ($q->{'name'} eq $::FORM{'namedcmd'}) {
splice(@{$::vars->{'user'}{'queries'}}, $count, 1);
last;
}
$count++;
}
print $cgi->header(); print $cgi->header();
# Generate and return the UI (HTML page) from the appropriate template. # Generate and return the UI (HTML page) from the appropriate template.
...@@ -317,6 +311,14 @@ elsif ($::FORM{'cmdtype'} eq "doit" && $::FORM{'remember'}) { ...@@ -317,6 +311,14 @@ elsif ($::FORM{'cmdtype'} eq "doit" && $::FORM{'remember'}) {
my $tofooter = $::FORM{'tofooter'} ? 1 : 0; my $tofooter = $::FORM{'tofooter'} ? 1 : 0;
$vars->{'message'} = "buglist_new_named_query";
# We want to display the correct message. Check if it existed before
# we insert, because ->queries may fetch from the db anyway
if (grep { $_->{name} eq $name } @{Bugzilla->user->queries()}) {
$vars->{'message'} = "buglist_updated_named_query";
}
SendSQL("SELECT query FROM namedqueries WHERE userid = $userid AND name = $qname"); SendSQL("SELECT query FROM namedqueries WHERE userid = $userid AND name = $qname");
if (FetchOneColumn()) { if (FetchOneColumn()) {
SendSQL("UPDATE namedqueries SendSQL("UPDATE namedqueries
...@@ -327,28 +329,11 @@ elsif ($::FORM{'cmdtype'} eq "doit" && $::FORM{'remember'}) { ...@@ -327,28 +329,11 @@ elsif ($::FORM{'cmdtype'} eq "doit" && $::FORM{'remember'}) {
SendSQL("REPLACE INTO namedqueries (userid, name, query, linkinfooter) SendSQL("REPLACE INTO namedqueries (userid, name, query, linkinfooter)
VALUES ($userid, $qname, $qbuffer, $tofooter)"); VALUES ($userid, $qname, $qbuffer, $tofooter)");
} }
my $new_in_footer = $tofooter; # Make sure to invalidate any cached query data, so that the footer is
$vars->{'message'} = "buglist_new_named_query"; # correctly displayed
Bugzilla->user->flush_queries_cache();
# Don't add it to the list if they are reusing an existing query name.
foreach my $query (@{$vars->{'user'}{'queries'}}) {
if ($query->{'name'} eq $name) {
$vars->{'message'} = "buglist_updated_named_query";
if ($query->{'linkinfooter'} == 1) {
$new_in_footer = 0;
}
last;
}
}
if ($new_in_footer) {
my %query = (name => $name,
query => $::buffer,
linkinfooter => $tofooter);
push(@{$vars->{'user'}{'queries'}}, \%query);
}
$vars->{'queryname'} = $name; $vars->{'queryname'} = $name;
} }
} }
......
...@@ -1385,7 +1385,7 @@ skip-networking ...@@ -1385,7 +1385,7 @@ skip-networking
positive check, which returns 1 (allow) if certain conditions are true, positive check, which returns 1 (allow) if certain conditions are true,
or a negative check, which returns 0 (deny.) E.g.: or a negative check, which returns 0 (deny.) E.g.:
<programlisting> if ($field eq "qacontact") { <programlisting> if ($field eq "qacontact") {
if (UserInGroup("quality_assurance")) { if (Bugzilla->user->groups("quality_assurance")) {
return 1; return 1;
} }
else { else {
...@@ -1395,7 +1395,7 @@ skip-networking ...@@ -1395,7 +1395,7 @@ skip-networking
This says that only users in the group "quality_assurance" can change This says that only users in the group "quality_assurance" can change
the QA Contact field of a bug. Getting more weird: the QA Contact field of a bug. Getting more weird:
<programlisting> if (($field eq "priority") && <programlisting> if (($field eq "priority") &&
($vars->{'user'}{'login'} =~ /.*\@example\.com$/)) (Bugzilla->user->email =~ /.*\@example\.com$/))
{ {
if ($oldvalue eq "P1") { if ($oldvalue eq "P1") {
return 1; return 1;
......
...@@ -34,6 +34,8 @@ use lib "."; ...@@ -34,6 +34,8 @@ use lib ".";
require "CGI.pl"; require "CGI.pl";
require "globals.pl"; require "globals.pl";
use Bugzilla::User;
# Shut up misguided -w warnings about "used only once". "use vars" just # Shut up misguided -w warnings about "used only once". "use vars" just
# doesn't work for me. # doesn't work for me.
...@@ -241,7 +243,7 @@ print Bugzilla->cgi->header(); ...@@ -241,7 +243,7 @@ print Bugzilla->cgi->header();
$editall = UserInGroup("editusers"); $editall = UserInGroup("editusers");
if (!$editall) { if (!$editall) {
if (!UserCanBlessAnything()) { if (!Bugzilla->user->can_bless) {
PutHeader("Not allowed"); PutHeader("Not allowed");
print "Sorry, you aren't a member of the 'editusers' group, and you\n"; print "Sorry, you aren't a member of the 'editusers' group, and you\n";
print "don't have permissions to put people in or out of any group.\n"; print "don't have permissions to put people in or out of any group.\n";
...@@ -483,7 +485,7 @@ if ($action eq 'new') { ...@@ -483,7 +485,7 @@ if ($action eq 'new') {
print "OK, done.<br>\n"; print "OK, done.<br>\n";
SendSQL("SELECT last_insert_id()"); SendSQL("SELECT last_insert_id()");
my ($newuserid) = FetchSQLData(); my ($newuserid) = FetchSQLData();
DeriveGroup($newuserid);
print "To change ${user}'s permissions, go back and <a href=\"editusers.cgi?action=edit&user=" . url_quote($user)."\">edit this user</A>"; print "To change ${user}'s permissions, go back and <a href=\"editusers.cgi?action=edit&user=" . url_quote($user)."\">edit this user</A>";
print "<p>\n"; print "<p>\n";
PutTrailer($localtrailer, PutTrailer($localtrailer,
...@@ -682,7 +684,9 @@ if ($action eq 'edit') { ...@@ -682,7 +684,9 @@ if ($action eq 'edit') {
my ($thisuserid, $realname, $disabledtext) = FetchSQLData(); my ($thisuserid, $realname, $disabledtext) = FetchSQLData();
if ($thisuserid > 0) { if ($thisuserid > 0) {
DeriveGroup($thisuserid); # Force groups to be up to date
my $changeduser = new Bugzilla::User($thisuserid);
$changeduser->derive_groups();
} }
print "<FORM METHOD=POST ACTION=editusers.cgi>\n"; print "<FORM METHOD=POST ACTION=editusers.cgi>\n";
print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n"; print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n";
...@@ -844,7 +848,8 @@ if ($action eq 'update') { ...@@ -844,7 +848,8 @@ if ($action eq 'update') {
print "Updated user's name.<BR>\n"; print "Updated user's name.<BR>\n";
} }
DeriveGroup($thisuserid); my $changeduser = new Bugzilla::User($thisuserid);
$changeduser->derive_groups();
PutTrailer($localtrailer); PutTrailer($localtrailer);
exit; exit;
......
...@@ -510,10 +510,9 @@ sub CanEditProductId { ...@@ -510,10 +510,9 @@ sub CanEditProductId {
my $query = "SELECT group_id FROM group_control_map " . my $query = "SELECT group_id FROM group_control_map " .
"WHERE product_id = $productid " . "WHERE product_id = $productid " .
"AND canedit != 0 "; "AND canedit != 0 ";
if ((defined @{$::vars->{user}{groupids}}) if (defined Bugzilla->user && %{Bugzilla->user->groups}) {
&& (@{$::vars->{user}{groupids}} > 0)) {
$query .= "AND group_id NOT IN(" . $query .= "AND group_id NOT IN(" .
join(',',@{$::vars->{user}{groupids}}) . ") "; join(',', values(%{Bugzilla->user->groups})) . ") ";
} }
$query .= "LIMIT 1"; $query .= "LIMIT 1";
PushGlobalSQLState(); PushGlobalSQLState();
...@@ -533,10 +532,9 @@ sub CanEnterProduct { ...@@ -533,10 +532,9 @@ sub CanEnterProduct {
"LEFT JOIN group_control_map " . "LEFT JOIN group_control_map " .
"ON group_control_map.product_id = products.id " . "ON group_control_map.product_id = products.id " .
"AND group_control_map.entry != 0 "; "AND group_control_map.entry != 0 ";
if ((defined @{$::vars->{user}{groupids}}) if (defined Bugzilla->user && %{Bugzilla->user->groups}) {
&& (@{$::vars->{user}{groupids}} > 0)) {
$query .= "AND group_id NOT IN(" . $query .= "AND group_id NOT IN(" .
join(',',@{$::vars->{user}{groupids}}) . ") "; join(',', values(%{Bugzilla->user->groups})) . ") ";
} }
$query .= "WHERE products.name = " . SqlQuote($productname) . " LIMIT 1"; $query .= "WHERE products.name = " . SqlQuote($productname) . " LIMIT 1";
PushGlobalSQLState(); PushGlobalSQLState();
...@@ -566,10 +564,9 @@ sub GetSelectableProducts { ...@@ -566,10 +564,9 @@ sub GetSelectableProducts {
$query .= "AND group_control_map.membercontrol = " . $query .= "AND group_control_map.membercontrol = " .
CONTROLMAPMANDATORY . " "; CONTROLMAPMANDATORY . " ";
} }
if ((defined @{$::vars->{user}{groupids}}) if (defined Bugzilla->user && %{Bugzilla->user->groups}) {
&& (@{$::vars->{user}{groupids}} > 0)) {
$query .= "AND group_id NOT IN(" . $query .= "AND group_id NOT IN(" .
join(',',@{$::vars->{user}{groupids}}) . ") "; join(',', values(%{Bugzilla->user->groups})) . ") ";
} }
$query .= "WHERE group_id IS NULL ORDER BY name"; $query .= "WHERE group_id IS NULL ORDER BY name";
PushGlobalSQLState(); PushGlobalSQLState();
...@@ -722,99 +719,6 @@ sub Crypt { ...@@ -722,99 +719,6 @@ sub Crypt {
return $cryptedpassword; return $cryptedpassword;
} }
# ConfirmGroup(userid) is called prior to any activity that relies
# on user_group_map to ensure that derived group permissions are up-to-date.
# Permissions must be rederived if ANY groups have a last_changed newer
# than the profiles.refreshed_when value.
sub ConfirmGroup {
my ($user, $locked) = (@_);
PushGlobalSQLState();
SendSQL("SELECT userid FROM profiles, groups WHERE userid = $user " .
"AND profiles.refreshed_when <= groups.last_changed ");
my $ret = FetchSQLData();
PopGlobalSQLState();
if ($ret) {
DeriveGroup($user, $locked);
}
}
# DeriveGroup removes and rederives all derived group permissions for
# the specified user. If $locked is true, Bugzilla has already locked
# the necessary tables as part of a larger transaction, so this function
# shouldn't lock them again (since then tables not part of this function's
# lock will get unlocked).
sub DeriveGroup {
my ($user, $locked) = (@_);
PushGlobalSQLState();
SendSQL("LOCK TABLES profiles WRITE, user_group_map WRITE, group_group_map READ, groups READ")
unless $locked;
# avoid races, we are only as up to date as the BEGINNING of this process
SendSQL("SELECT login_name, NOW() FROM profiles WHERE userid = $user");
my ($login, $starttime) = FetchSQLData();
# first remove any old derived stuff for this user
SendSQL("DELETE FROM user_group_map WHERE user_id = $user " .
"AND isderived = 1");
my %groupidsadded = ();
# add derived records for any matching regexps
SendSQL("SELECT id, userregexp FROM groups WHERE userregexp != ''");
while (MoreSQLData()) {
my ($groupid, $rexp) = FetchSQLData();
if ($login =~ m/$rexp/i) {
PushGlobalSQLState();
$groupidsadded{$groupid} = 1;
SendSQL("INSERT INTO user_group_map " .
"(user_id, group_id, isbless, isderived) " .
"VALUES ($user, $groupid, 0, 1)");
PopGlobalSQLState();
}
}
# Get a list of the groups of which the user is a member.
my %groupidschecked = ();
my @groupidstocheck = ();
SendSQL("SELECT group_id FROM user_group_map WHERE user_id = $user
AND NOT isbless");
while (MoreSQLData()) {
my ($groupid) = FetchSQLData();
push(@groupidstocheck,$groupid);
}
# Each group needs to be checked for inherited memberships once.
while (@groupidstocheck) {
my $group = shift @groupidstocheck;
if (!defined($groupidschecked{"$group"})) {
$groupidschecked{"$group"} = 1;
SendSQL("SELECT grantor_id FROM group_group_map WHERE"
. " member_id = $group AND NOT isbless");
while (MoreSQLData()) {
my ($groupid) = FetchSQLData();
if (!defined($groupidschecked{"$groupid"})) {
push(@groupidstocheck,$groupid);
}
if (!$groupidsadded{$groupid}) {
$groupidsadded{$groupid} = 1;
PushGlobalSQLState();
SendSQL("INSERT INTO user_group_map"
. " (user_id, group_id, isbless, isderived)"
. " VALUES ($user, $groupid, 0, 1)");
PopGlobalSQLState();
}
}
}
}
SendSQL("UPDATE profiles SET refreshed_when = " .
SqlQuote($starttime) . "WHERE userid = $user");
SendSQL("UNLOCK TABLES");
PopGlobalSQLState();
};
sub DBID_to_real_or_loginname { sub DBID_to_real_or_loginname {
my ($id) = (@_); my ($id) = (@_);
PushGlobalSQLState(); PushGlobalSQLState();
...@@ -1189,23 +1093,8 @@ sub SplitEnumType { ...@@ -1189,23 +1093,8 @@ sub SplitEnumType {
return @result; return @result;
} }
# UserInGroup returns information aboout the current user if no second
# parameter is specified
sub UserInGroup { sub UserInGroup {
my ($groupname, $userid) = (@_); return defined Bugzilla->user && defined Bugzilla->user->groups->{$_[0]};
if (!$userid) {
return $::vars->{'user'}{'groups'}{$_[0]};
}
PushGlobalSQLState();
$userid ||= $::userid;
SendSQL("SELECT groups.id FROM groups, user_group_map
WHERE groups.id = user_group_map.group_id
AND user_group_map.user_id = $userid
AND isbless = 0
AND groups.name = " . SqlQuote($groupname));
my $result = FetchOneColumn();
PopGlobalSQLState();
return defined($result);
} }
sub UserCanBlessGroup { sub UserCanBlessGroup {
...@@ -1238,32 +1127,6 @@ sub UserCanBlessGroup { ...@@ -1238,32 +1127,6 @@ sub UserCanBlessGroup {
return $result; return $result;
} }
sub UserCanBlessAnything {
PushGlobalSQLState();
# check if user explicitly can bless a group
SendSQL("SELECT group_id FROM user_group_map
WHERE user_id = $::userid AND isbless = 1");
my $result = FetchOneColumn();
PopGlobalSQLState();
if ($result) {
return 1;
}
PushGlobalSQLState();
# check if user is a member of a group that can bless this group
SendSQL("SELECT groups.id FROM groups, user_group_map,
group_group_map
WHERE groups.id = grantor_id
AND user_group_map.user_id = $::userid
AND group_group_map.isbless = 1
AND user_group_map.group_id = member_id");
$result = FetchOneColumn();
PopGlobalSQLState();
if ($result) {
return 1;
}
return 0;
}
sub BugInGroup { sub BugInGroup {
my ($bugid, $groupname) = (@_); my ($bugid, $groupname) = (@_);
PushGlobalSQLState(); PushGlobalSQLState();
......
...@@ -54,7 +54,7 @@ sub sillyness { ...@@ -54,7 +54,7 @@ sub sillyness {
use vars qw($vars $template); use vars qw($vars $template);
ConnectToDatabase(); ConnectToDatabase();
my $whoid = confirm_login(); my $user = confirm_login();
my $cgi = Bugzilla->cgi; my $cgi = Bugzilla->cgi;
...@@ -454,7 +454,7 @@ if (UserInGroup("editbugs")) { ...@@ -454,7 +454,7 @@ if (UserInGroup("editbugs")) {
"($id, $i)"); "($id, $i)");
push(@all_deps, $i); # list for mailing dependent bugs push(@all_deps, $i); # list for mailing dependent bugs
# Log the activity for the other bug: # Log the activity for the other bug:
LogActivityEntry($i, $me, "", $id, $whoid, $timestamp); LogActivityEntry($i, $me, "", $id, $user->id, $timestamp);
} }
my $tmp = $me; my $tmp = $me;
$me = $target; $me = $target;
......
...@@ -57,7 +57,8 @@ use vars qw(%versions ...@@ -57,7 +57,8 @@ use vars qw(%versions
); );
ConnectToDatabase(); ConnectToDatabase();
my $whoid = confirm_login(); my $user = confirm_login();
my $whoid = $user->id;
my $cgi = Bugzilla->cgi; my $cgi = Bugzilla->cgi;
...@@ -1093,9 +1094,10 @@ foreach my $id (@idlist) { ...@@ -1093,9 +1094,10 @@ foreach my $id (@idlist) {
"keywords $write, longdescs $write, fielddefs $write, " . "keywords $write, longdescs $write, fielddefs $write, " .
"bug_group_map $write, flags $write, duplicates $write," . "bug_group_map $write, flags $write, duplicates $write," .
# user_group_map would be a READ lock except that Flag::process # user_group_map would be a READ lock except that Flag::process
# may call Flag::notify, which calls ConfirmGroup, which might # may call Flag::notify, which creates a new user object,
# call DeriveGroup, which wants a WRITE lock on that table. # which might call derive_groups, which wants a WRITE lock on that
# group_group_map is in here at all because DeriveGroups needs it. # table. group_group_map is in here at all because derive_groups
# needs it.
"user_group_map $write, group_group_map READ, flagtypes READ, " . "user_group_map $write, group_group_map READ, flagtypes READ, " .
"flaginclusions AS i READ, flagexclusions AS e READ, " . "flaginclusions AS i READ, flagexclusions AS e READ, " .
"keyworddefs READ, groups READ, attachments READ, " . "keyworddefs READ, groups READ, attachments READ, " .
......
...@@ -53,19 +53,21 @@ ConnectToDatabase(); ...@@ -53,19 +53,21 @@ ConnectToDatabase();
my $cgi = Bugzilla->cgi; my $cgi = Bugzilla->cgi;
my $userid = 0;
if (defined $::FORM{"GoAheadAndLogIn"}) { if (defined $::FORM{"GoAheadAndLogIn"}) {
# We got here from a login page, probably from relogin.cgi. We better # We got here from a login page, probably from relogin.cgi. We better
# make sure the password is legit. # make sure the password is legit.
$userid = confirm_login(); confirm_login();
} else { } else {
$userid = quietly_check_login(); quietly_check_login();
} }
my $user = Bugzilla->user;
my $userid = $user ? $user->id : 0;
# Backwards compatibility hack -- if there are any of the old QUERY_* # Backwards compatibility hack -- if there are any of the old QUERY_*
# cookies around, and we are logged in, then move them into the database # cookies around, and we are logged in, then move them into the database
# and nuke the cookie. This is required for Bugzilla 2.8 and earlier. # and nuke the cookie. This is required for Bugzilla 2.8 and earlier.
if ($userid) { if ($user) {
my @oldquerycookies; my @oldquerycookies;
foreach my $i (keys %::COOKIE) { foreach my $i (keys %::COOKIE) {
if ($i =~ /^QUERY_(.*)$/) { if ($i =~ /^QUERY_(.*)$/) {
...@@ -97,7 +99,7 @@ if ($userid) { ...@@ -97,7 +99,7 @@ if ($userid) {
} }
if ($::FORM{'nukedefaultquery'}) { if ($::FORM{'nukedefaultquery'}) {
if ($userid) { if ($user) {
SendSQL("DELETE FROM namedqueries " . SendSQL("DELETE FROM namedqueries " .
"WHERE userid = $userid AND name = '$::defaultqueryname'"); "WHERE userid = $userid AND name = '$::defaultqueryname'");
} }
...@@ -105,7 +107,7 @@ if ($::FORM{'nukedefaultquery'}) { ...@@ -105,7 +107,7 @@ if ($::FORM{'nukedefaultquery'}) {
} }
my $userdefaultquery; my $userdefaultquery;
if ($userid) { if ($user) {
SendSQL("SELECT query FROM namedqueries " . SendSQL("SELECT query FROM namedqueries " .
"WHERE userid = $userid AND name = '$::defaultqueryname'"); "WHERE userid = $userid AND name = '$::defaultqueryname'");
$userdefaultquery = FetchOneColumn(); $userdefaultquery = FetchOneColumn();
...@@ -308,7 +310,6 @@ $vars->{'rep_platform'} = \@::legal_platform; ...@@ -308,7 +310,6 @@ $vars->{'rep_platform'} = \@::legal_platform;
$vars->{'op_sys'} = \@::legal_opsys; $vars->{'op_sys'} = \@::legal_opsys;
$vars->{'priority'} = \@::legal_priority; $vars->{'priority'} = \@::legal_priority;
$vars->{'bug_severity'} = \@::legal_severity; $vars->{'bug_severity'} = \@::legal_severity;
$vars->{'userid'} = $userid;
# Boolean charts # Boolean charts
my @fields; my @fields;
...@@ -362,7 +363,7 @@ for (my $chart = 0; $::FORM{"field$chart-0-0"}; $chart++) { ...@@ -362,7 +363,7 @@ for (my $chart = 0; $::FORM{"field$chart-0-0"}; $chart++) {
$default{'charts'} = \@charts; $default{'charts'} = \@charts;
# Named queries # Named queries
if ($userid) { if ($user) {
my @namedqueries; my @namedqueries;
SendSQL("SELECT name FROM namedqueries " . SendSQL("SELECT name FROM namedqueries " .
"WHERE userid = $userid AND name != '$::defaultqueryname' " . "WHERE userid = $userid AND name != '$::defaultqueryname' " .
......
...@@ -59,7 +59,9 @@ $cgi->send_cookie(-name => "Bugzilla_logincookie", ...@@ -59,7 +59,9 @@ $cgi->send_cookie(-name => "Bugzilla_logincookie",
delete $::COOKIE{"Bugzilla_login"}; delete $::COOKIE{"Bugzilla_login"};
$vars->{'message'} = "logged_out"; $vars->{'message'} = "logged_out";
$vars->{'user'} = {};
# This entire script should eventually just become a call to Bugzilla->logout
Bugzilla->logout;
print $cgi->header(); print $cgi->header();
$template->process("global/message.html.tmpl", $vars) $template->process("global/message.html.tmpl", $vars)
......
...@@ -106,12 +106,16 @@ if (exists $::FORM{'rederivegroups'}) { ...@@ -106,12 +106,16 @@ if (exists $::FORM{'rederivegroups'}) {
} }
# rederivegroupsnow is REALLY only for testing. # rederivegroupsnow is REALLY only for testing.
# If it wasn't, then we'd do this the faster way as a per-group
# thing rather than per-user for group inheritance
if (exists $::FORM{'rederivegroupsnow'}) { if (exists $::FORM{'rederivegroupsnow'}) {
require Bugzilla::User;
Status("OK, now rederiving groups."); Status("OK, now rederiving groups.");
SendSQL("SELECT userid FROM profiles"); SendSQL("SELECT userid FROM profiles");
while ((my $id) = FetchSQLData()) { while ((my $id) = FetchSQLData()) {
DeriveGroup($id); my $user = new Bugzilla::User($id);
Status("Group $id"); $user->derive_groups();
Status("User $id");
} }
} }
......
...@@ -35,26 +35,6 @@ my $cgi = Bugzilla->cgi; ...@@ -35,26 +35,6 @@ my $cgi = Bugzilla->cgi;
# Main Body Execution # Main Body Execution
############################################################################### ###############################################################################
$vars->{'username'} = $::COOKIE{'Bugzilla_login'} || '';
if (defined $::COOKIE{'Bugzilla_login'}) {
SendSQL("SELECT mybugslink, userid FROM profiles " .
"WHERE login_name = " . SqlQuote($::COOKIE{'Bugzilla_login'}));
my ($mybugslink, $userid) = (FetchSQLData());
$vars->{'userid'} = $userid;
$vars->{'canblessanything'} = UserCanBlessAnything();
if ($mybugslink) {
my $mybugstemplate = Param("mybugstemplate");
my %substs = ( 'userid' => url_quote($::COOKIE{'Bugzilla_login'}) );
$vars->{'mybugsurl'} = PerformSubsts($mybugstemplate, \%substs);
}
SendSQL("SELECT name FROM namedqueries WHERE userid = $userid AND linkinfooter");
while (MoreSQLData()) {
my ($name) = FetchSQLData();
push(@{$vars->{'namedqueries'}}, $name);
}
}
# This sidebar is currently for use with Mozilla based web browsers. # This sidebar is currently for use with Mozilla based web browsers.
# Internet Explorer 6 is supposed to have a similar feature, but it # Internet Explorer 6 is supposed to have a similar feature, but it
# most likely won't support XUL ;) When that does come out, this # most likely won't support XUL ;) When that does come out, this
......
...@@ -123,7 +123,8 @@ ...@@ -123,7 +123,8 @@
[% END %] [% END %]
</td> </td>
</tr> </tr>
[% IF (user.userid != bugassignee_id) AND UserInGroup("editbugs") %]
[% IF (user.id != bugassignee_id) AND user.groups.editbugs %]
<tr> <tr>
<th>Reassignment:</th> <th>Reassignment:</th>
<td> <td>
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
<bugzilla version="[% VERSION %]" <bugzilla version="[% VERSION %]"
urlbase="[% Param('urlbase') %]" urlbase="[% Param('urlbase') %]"
maintainer="[% Param('maintainer') FILTER xml %]" maintainer="[% Param('maintainer') FILTER xml %]"
[% IF user.login %] [% IF user %]
exporter="[% user.login FILTER xml %]" exporter="[% user.login FILTER xml %]"
[% END %] [% END %]
> >
......
...@@ -116,7 +116,7 @@ ...@@ -116,7 +116,7 @@
id="requestee-[% flag.id %]" id="requestee-[% flag.id %]"
name="requestee-[% flag.id %]" name="requestee-[% flag.id %]"
[% IF flag.status == "?" && flag.requestee %] [% IF flag.status == "?" && flag.requestee %]
value="[% flag.requestee.email FILTER html %]" value="[% flag.requestee.login FILTER html %]"
[% END %] [% END %]
>) >)
</span> </span>
......
...@@ -19,19 +19,6 @@ ...@@ -19,19 +19,6 @@
# Contributor(s): Gervase Markham <gerv@gerv.net> # Contributor(s): Gervase Markham <gerv@gerv.net>
#%] #%]
[%# INTERFACE:
# user: hash. Information about the user. If the user is not logged in,
# user.login is undefined.
# login: string. The user's Bugzilla login email address.
# showmybugslink: boolean. True if user wants My Bugs in the footer.
# queries: list of strings. The names of those of the user's named
# queries which should be displayed in the footer.
# groups: hash. Keys are group names, values are true if user in that group.
# The keys used in this template are
# tweakparams, editcomponents, creategroups, editkeywords, confirm,
# editbugs, editusers.
#%]
[%# Migration note: this whole file corresponds to the old %commandmenu% [%# Migration note: this whole file corresponds to the old %commandmenu%
substitution param in 'footerhtml' %] substitution param in 'footerhtml' %]
...@@ -51,14 +38,14 @@ ...@@ -51,14 +38,14 @@
<a href="report.cgi">Reports</a> <a href="report.cgi">Reports</a>
[% IF user.login %] [% IF user %]
[% email = user.login FILTER url_quote %] [% email = user.login FILTER url_quote %]
| <a href="request.cgi?requester=[% email %]&amp;requestee=[% email %]&amp;do_union=1&amp;group=type">My Requests</a> | <a href="request.cgi?requester=[% email %]&amp;requestee=[% email %]&amp;do_union=1&amp;group=type">My Requests</a>
[% ELSE %] [% ELSE %]
| <a href="request.cgi">Requests</a> | <a href="request.cgi">Requests</a>
[% END %] [% END %]
[% IF user.login && Param('usevotes') %] [% IF user && Param('usevotes') %]
| <a href="votes.cgi?action=show_user">My Votes</a> | <a href="votes.cgi?action=show_user">My Votes</a>
[% END %] [% END %]
</td> </td>
...@@ -72,7 +59,7 @@ ...@@ -72,7 +59,7 @@
[% ', <a href="editparams.cgi">parameters</a>' [% ', <a href="editparams.cgi">parameters</a>'
IF user.groups.tweakparams %] IF user.groups.tweakparams %]
[% ', <a href="editusers.cgi">users</a>' IF user.groups.editusers [% ', <a href="editusers.cgi">users</a>' IF user.groups.editusers
|| user.canblessany %] || user.can_bless %]
[% ', <a href="editproducts.cgi">products</a>' [% ', <a href="editproducts.cgi">products</a>'
IF user.groups.editcomponents %] IF user.groups.editcomponents %]
[% ', <a href="editflagtypes.cgi">flags</a>' [% ', <a href="editflagtypes.cgi">flags</a>'
...@@ -91,9 +78,14 @@ ...@@ -91,9 +78,14 @@
[%# Preset queries %] [%# Preset queries %]
[% preset_queries = user.showmybugslink %] [% preset_queries = user.showmybugslink %]
[% FOREACH q = user.queries %] [% IF NOT preset_queries %]
[% SET preset_queries = 1 IF q.linkinfooter %] [% FOREACH q = user.queries %]
[% END %] [% IF q.linkinfooter %]
[% preset_queries = 1 %]
[% LAST %]
[% END %]
[% END %]
[% END %]
<tr> <tr>
[% IF preset_queries %] [% IF preset_queries %]
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
<p> <p>
<font color="red"> <font color="red">
Your quip '<tt>[% added_quip FILTER html %]</tt>' has been added. Your quip '<tt>[% added_quip FILTER html %]</tt>' has been added.
[% IF Param("enablequips") == "approved" AND !UserInGroup('admin') %] [% IF Param("enablequips") == "approved" AND !user.groups.admin %]
It will be used as soon as it gets approved. It will be used as soon as it gets approved.
[% END %] [% END %]
</font> </font>
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
Bugzilla will pick a random quip for the headline on each bug list, and Bugzilla will pick a random quip for the headline on each bug list, and
you can extend the quip list. Type in something clever or funny or boring you can extend the quip list. Type in something clever or funny or boring
(but not obscene or offensive, please) and bonk on the button. (but not obscene or offensive, please) and bonk on the button.
[% IF Param("enablequips") == "approved" AND !UserInGroup('admin') %] [% IF Param("enablequips") == "approved" AND !user.groups.admin %]
Note that your quip has to be approved before it is used. Note that your quip has to be approved before it is used.
[% END %] [% END %]
</p> </p>
......
...@@ -43,7 +43,7 @@ Subject: [% flag.type.name %] [%+ subject_status %]: [Bug [% flag.target.bug.id ...@@ -43,7 +43,7 @@ Subject: [% flag.type.name %] [%+ subject_status %]: [Bug [% flag.target.bug.id
[%+ USE wrap -%] [%+ USE wrap -%]
[%- FILTER bullet = wrap(80) -%] [%- FILTER bullet = wrap(80) -%]
[% user.realname %] <[% user.login %]> has [% statuses.${flag.status} %] [%+ to_identity %] for [% flag.type.name %]: [% user.identity %] has [% statuses.${flag.status} %] [%+ to_identity %] for [% flag.type.name %]:
Bug [% bugidsummary %] Bug [% bugidsummary %]
[% END %] [% END %]
...@@ -58,7 +58,7 @@ Attachment [% attidsummary %] ...@@ -58,7 +58,7 @@ Attachment [% attidsummary %]
[%- FILTER bullet = wrap(80) %] [%- FILTER bullet = wrap(80) %]
[% IF form.comment.length > 0 %] [% IF form.comment.length > 0 %]
------- Additional Comments from [% user.realname %] <[% user.login %]> ------- Additional Comments from [% user.identity %]
[%+ form.comment %] [%+ form.comment %]
[% END %] [% END %]
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
"Last Changed" => "Last Changed" } %] "Last Changed" => "Last Changed" } %]
<br> <br>
[% IF NOT userid %] [% IF NOT user %]
<input type="hidden" name="cmdtype" value="doit"> <input type="hidden" name="cmdtype" value="doit">
[% ELSE %] [% ELSE %]
<script type="text/javascript"> <!-- <script type="text/javascript"> <!--
......
...@@ -72,37 +72,38 @@ function normal_keypress_handler( aEvent ) { ...@@ -72,37 +72,38 @@ function normal_keypress_handler( aEvent ) {
<text class="text-link" onclick="load_relative_url('enter_bug.cgi')" value="new bug"/> <text class="text-link" onclick="load_relative_url('enter_bug.cgi')" value="new bug"/>
<separator class="thin"/> <separator class="thin"/>
[% IF username %] [% IF user %]
<text class="text-link" onclick="load_relative_url('userprefs.cgi')" value="edit prefs"/> <text class="text-link" onclick="load_relative_url('userprefs.cgi')" value="edit prefs"/>
[%- IF UserInGroup('tweakparams') %] [%- IF user.groups.tweakparams %]
<text class="text-link" onclick="load_relative_url('editparams.cgi')" value="edit params"/> <text class="text-link" onclick="load_relative_url('editparams.cgi')" value="edit params"/>
[%- END %] [%- END %]
[%- IF UserInGroup('editusers') || canblessany %] [%- IF user.groups.editusers || user.can_bless %]
<text class="text-link" onclick="load_relative_url('editusers.cgi')" value="edit users"/> <text class="text-link" onclick="load_relative_url('editusers.cgi')" value="edit users"/>
[%- END %] [%- END %]
[%- IF UserInGroup('editcomponents') %] [%- IF user.groups.editcomponents %]
<text class="text-link" onclick="load_relative_url('editcomponents.cgi')" value="edit components"/> <text class="text-link" onclick="load_relative_url('editcomponents.cgi')" value="edit components"/>
[%- END %] [%- END %]
[%- IF UserInGroup('creategroups') %] [%- IF user.groups.creategroups %]
<text class="text-link" onclick="load_relative_url('editgroups.cgi')" value="edit groups"/> <text class="text-link" onclick="load_relative_url('editgroups.cgi')" value="edit groups"/>
[%- END %] [%- END %]
[%- IF UserInGroup('editkeywords') %] [%- IF user.groups.editkeywords %]
<text class="text-link" onclick="load_relative_url('editkeywords.cgi')" value="edit keywords"/> <text class="text-link" onclick="load_relative_url('editkeywords.cgi')" value="edit keywords"/>
[%- END %] [%- END %]
[%- IF UserInGroup('tweakparams') %] [%- IF user.groups.tweakparams %]
<text class="text-link" onclick="load_relative_url('sanitycheck.cgi')" value="sanity check"/> <text class="text-link" onclick="load_relative_url('sanitycheck.cgi')" value="sanity check"/>
[%- END %] [%- END %]
<text class="text-link" onclick="load_relative_url('relogin.cgi')" value="logout [% username FILTER html %]"/> <text class="text-link" onclick="load_relative_url('relogin.cgi')" value="logout [% user.login FILTER html %]"/>
<separator class="thin"/> <separator class="thin"/>
[%- IF mybugsurl %] [%- IF user.showmybugslink %]
<text class="text-link" onclick="load_relative_url('[% mybugsurl FILTER html %]')" value="my bugs"/> [% filtered_username = user.login FILTER url_quote %]
<text class="text-link" onclick="load_relative_url('[% Param('mybugstemplate').replace('%userid%', filtered_username) FILTER js FILTER html %]')" value="my bugs"/>
[%- END %] [%- END %]
[%- IF Param('usevotes') %] [%- IF Param('usevotes') %]
<text class="text-link" onclick="load_relative_url('votes.cgi?action=show_user')" value="my votes"/> <text class="text-link" onclick="load_relative_url('votes.cgi?action=show_user')" value="my votes"/>
[%- END %] [%- END %]
[%- FOREACH name = namedqueries %] [%- FOREACH q = user.queries %]
<text class="text-link" onclick="load_relative_url('buglist.cgi?cmdtype=runnamed&amp;namedcmd=[% name FILTER url_quote %]')" value="[% name FILTER html %]"/> <text class="text-link" onclick="load_relative_url('buglist.cgi?cmdtype=runnamed&amp;namedcmd=[% q.name FILTER url_quote %]')" value="[% q.name FILTER html %]"/>
[% END %] [% END %]
[% ELSE %] [% ELSE %]
......
...@@ -44,6 +44,8 @@ quietly_check_login('permit_anonymous'); ...@@ -44,6 +44,8 @@ quietly_check_login('permit_anonymous');
# token-related tasks. # token-related tasks.
use Token; use Token;
use Bugzilla::User;
################################################################################ ################################################################################
# Data Validation / Security Authorization # Data Validation / Security Authorization
################################################################################ ################################################################################
...@@ -248,7 +250,10 @@ sub changeEmail { ...@@ -248,7 +250,10 @@ sub changeEmail {
SendSQL("DELETE FROM tokens WHERE userid = $userid SendSQL("DELETE FROM tokens WHERE userid = $userid
AND tokentype = 'emailnew'"); AND tokentype = 'emailnew'");
SendSQL("UNLOCK TABLES"); SendSQL("UNLOCK TABLES");
DeriveGroup($userid);
# The email address has been changed, so we need to rederive the groups
my $user = new Bugzilla::User($userid);
$user->derive_groups;
# Return HTTP response headers. # Return HTTP response headers.
print Bugzilla->cgi->header(); print Bugzilla->cgi->header();
...@@ -283,7 +288,16 @@ sub cancelChangeEmail { ...@@ -283,7 +288,16 @@ sub cancelChangeEmail {
SET login_name = $quotedoldemail SET login_name = $quotedoldemail
WHERE userid = $userid"); WHERE userid = $userid");
SendSQL("UNLOCK TABLES"); SendSQL("UNLOCK TABLES");
DeriveGroup($userid);
# email has changed, so rederive groups
# Note that this is done _after_ the tables are unlocked
# This is sort of a race condition (given the lack of transactions)
# but the user had access to it just now, so it's not a security
# issue
my $user = new Bugzilla::User($userid);
$user->derive_groups;
$vars->{'message'} = "email_change_cancelled_reinstated"; $vars->{'message'} = "email_change_cancelled_reinstated";
} }
} }
......
...@@ -314,8 +314,13 @@ sub SaveFooter { ...@@ -314,8 +314,13 @@ sub SaveFooter {
SendSQL("UPDATE profiles SET mybugslink = " . SendSQL("UPDATE profiles SET mybugslink = " .
SqlQuote($::FORM{'mybugslink'}) . " WHERE userid = $userid"); SqlQuote($::FORM{'mybugslink'}) . " WHERE userid = $userid");
# Regenerate cached info about queries in footer. # Make sure that cached queries in the user object are invalidated
$vars->{'user'} = GetUserInfo($::userid); # so that the footer is correct
my $user = Bugzilla->user;
$user->flush_queries_cache();
# Also need to update showmybugslink
$user->{showmybugslink} = $::FORM{'mybugslink'} ? 1 : 0;
} }
......
...@@ -127,7 +127,7 @@ sub show_user { ...@@ -127,7 +127,7 @@ sub show_user {
# If a bug_id is given, and we're editing, we'll add it to the votes list. # If a bug_id is given, and we're editing, we'll add it to the votes list.
my $bug_id = $::FORM{'bug_id'} || ""; my $bug_id = $::FORM{'bug_id'} || "";
my $name = $::FORM{'user'} || $::COOKIE{'Bugzilla_login'}; my $name = $::FORM{'user'} || Bugzilla->user->login;
my $who = DBname_to_id($name); my $who = DBname_to_id($name);
# After DBNameToIdAndCheck is templatised and prints a Content-Type, # After DBNameToIdAndCheck is templatised and prints a Content-Type,
...@@ -135,7 +135,7 @@ sub show_user { ...@@ -135,7 +135,7 @@ sub show_user {
# special error handling should go away. # special error handling should go away.
$who || ThrowUserError("invalid_username", {name => $name}); $who || ThrowUserError("invalid_username", {name => $name});
my $canedit = 1 if ($name eq $::COOKIE{'Bugzilla_login'}); my $canedit = 1 if ($name eq Bugzilla->user->login);
SendSQL("LOCK TABLES bugs READ, products READ, votes WRITE, SendSQL("LOCK TABLES bugs READ, products READ, votes WRITE,
cc READ, bug_group_map READ, user_group_map READ, cc READ, bug_group_map READ, user_group_map READ,
...@@ -270,7 +270,7 @@ sub record_votes { ...@@ -270,7 +270,7 @@ sub record_votes {
GetVersionTable(); GetVersionTable();
my $who = DBNameToIdAndCheck($::COOKIE{'Bugzilla_login'}); my $who = Bugzilla->user->id;
# If the user is voting for bugs, make sure they aren't overstuffing # If the user is voting for bugs, make sure they aren't overstuffing
# the ballot box. # the ballot box.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment