Patch for bug 180879: Implement privs for bug flags modification; patch by Fr�d�ric Buclin <LpSolit@netscape.net>, r=joel, a=justdave.

This commit is contained in:
jocuri%softhome.net 2004-11-23 22:41:44 +00:00
Родитель 16735ddc71
Коммит 0ecd04b79e
8 изменённых файлов: 154 добавлений и 9 удалений

Просмотреть файл

@ -139,6 +139,7 @@ sub count {
sub validate {
# Validates fields containing flag modifications.
my $user = Bugzilla->user;
my ($data, $bug_id) = @_;
# Get a list of flags to validate. Uses the "map" function
@ -213,6 +214,24 @@ sub validate {
}
}
}
# Make sure the user is authorized to modify flags, see bug 180879
# - The flag is unchanged
next if ($status eq $flag->{status});
# - User can clear flags set by itself
next if (($status eq "X") && ($user->id eq $flag->{setter}));
# - User in the $grant_gid group can set/clear flags,
# including "+" and "-"
next if (!$flag->{type}->{grant_gid}
|| $user->in_group(&::GroupIdToName($flag->{type}->{grant_gid})));
# - Any other flag modification is denied
ThrowUserError("flag_update_denied",
{ name => $flag->{type}->{name},
status => $status,
old_status => $flag->{status} });
}
}

Просмотреть файл

@ -49,7 +49,8 @@ my @base_columns =
("1", "flagtypes.id", "flagtypes.name", "flagtypes.description",
"flagtypes.cc_list", "flagtypes.target_type", "flagtypes.sortkey",
"flagtypes.is_active", "flagtypes.is_requestable",
"flagtypes.is_requesteeble", "flagtypes.is_multiplicable");
"flagtypes.is_requesteeble", "flagtypes.is_multiplicable",
"flagtypes.grant_group_id", "flagtypes.request_group_id");
# Note: when adding tables to @base_tables, make sure to include the separator
# (i.e. a comma or words like "LEFT OUTER JOIN") before the table name,
@ -181,6 +182,7 @@ sub count {
}
sub validate {
my $user = Bugzilla->user;
my ($data, $bug_id, $attach_id) = @_;
# Get a list of flag types to validate. Uses the "map" function
@ -249,6 +251,22 @@ sub validate {
attach_id => $attach_id });
}
}
# Make sure the user is authorized to modify flags, see bug 180879
# - User in the $grant_gid group can set flags, including "+" and "-"
next if (!$flag_type->{grant_gid}
|| $user->in_group(&::GroupIdToName($flag_type->{grant_gid})));
# - User in the $request_gid group can request flags
next if ($status eq '?'
&& (!$flag_type->{request_gid}
|| $user->in_group(&::GroupIdToName($flag_type->{request_gid}))));
# - Any other flag modification is denied
ThrowUserError("flag_update_denied",
{ name => $flag_type->{name},
status => $status,
old_status => "X" });
}
}
@ -348,6 +366,12 @@ sub sqlify_criteria {
push(@$columns, "COUNT(flagexclusions.type_id) AS num_exclusions");
$$having = "num_exclusions = 0";
}
if ($criteria->{group}) {
my $gid = $criteria->{group};
detaint_natural($gid);
push(@criteria, "(flagtypes.grant_group_id = $gid " .
" OR flagtypes.request_group_id = $gid)");
}
return @criteria;
}
@ -368,7 +392,9 @@ sub perlify_record {
$type->{'is_requestable'} = $_[8];
$type->{'is_requesteeble'} = $_[9];
$type->{'is_multiplicable'} = $_[10];
$type->{'flag_count'} = $_[11];
$type->{'grant_gid'} = $_[11];
$type->{'request_gid'} = $_[12];
$type->{'flag_count'} = $_[13];
return $type;
}

Просмотреть файл

@ -1685,7 +1685,9 @@ $table{flagtypes} =
is_requesteeble TINYINT NOT NULL DEFAULT 0 ,
is_multiplicable TINYINT NOT NULL DEFAULT 0 ,
sortkey SMALLINT NOT NULL DEFAULT 0
sortkey SMALLINT NOT NULL DEFAULT 0 ,
grant_group_id MEDIUMINT NULL ,
request_group_id MEDIUMINT NULL
';
$table{flaginclusions} =
@ -4124,6 +4126,11 @@ if (GetFieldDef("group_group_map", "isbless")) {
# login data source
AddField("profiles", "extern_id", "varchar(64)");
# 2004-11-20 - LpSolit@netscape.net - Bug 180879
# Add grant and request groups for flags
AddField('flagtypes', 'grant_group_id', 'mediumint null');
AddField('flagtypes', 'request_group_id', 'mediumint null');
# If you had to change the --TABLE-- definition in any way, then add your
# differential change code *** A B O V E *** this comment.
#

Просмотреть файл

@ -90,9 +90,12 @@ exit;
sub list {
# Define the variables and functions that will be passed to the UI template.
$vars->{'bug_types'} = Bugzilla::FlagType::match({ 'target_type' => 'bug' }, 1);
$vars->{'bug_types'} =
Bugzilla::FlagType::match({ 'target_type' => 'bug',
'group' => $::FORM{'group'} }, 1);
$vars->{'attachment_types'} =
Bugzilla::FlagType::match({ 'target_type' => 'attachment' }, 1);
Bugzilla::FlagType::match({ 'target_type' => 'attachment',
'group' => $::FORM{'group'} }, 1);
# Return the appropriate HTTP response headers.
print Bugzilla->cgi->header();
@ -129,6 +132,13 @@ sub edit {
$vars->{'type'} = Bugzilla::FlagType::get($::FORM{'id'});
$vars->{'type'}->{'inclusions'} = Bugzilla::FlagType::get_inclusions($::FORM{'id'});
$vars->{'type'}->{'exclusions'} = Bugzilla::FlagType::get_exclusions($::FORM{'id'});
# Users want to see group names, not IDs
foreach my $group ("grant_gid", "request_gid") {
my $gid = $vars->{'type'}->{$group};
next if (!$gid);
SendSQL("SELECT name FROM groups WHERE id = $gid");
$vars->{'type'}->{$group} = FetchOneColumn();
}
}
# Otherwise set the target type (the minimal information about the type
# that the template needs to know) from the URL parameter and default
@ -208,6 +218,7 @@ sub insert {
validateIsRequestable();
validateIsRequesteeble();
validateAllowMultiple();
validateGroups();
my $name = SqlQuote($::FORM{'name'});
my $description = SqlQuote($::FORM{'description'});
@ -224,11 +235,13 @@ sub insert {
# Insert a record for the new flag type into the database.
SendSQL("INSERT INTO flagtypes (id, name, description, cc_list,
target_type, sortkey, is_active, is_requestable,
is_requesteeble, is_multiplicable)
is_requesteeble, is_multiplicable,
grant_group_id, request_group_id)
VALUES ($id, $name, $description, $cc_list, '$target_type',
$::FORM{'sortkey'}, $::FORM{'is_active'},
$::FORM{'is_requestable'}, $::FORM{'is_requesteeble'},
$::FORM{'is_multiplicable'})");
$::FORM{'is_multiplicable'}, $::FORM{'grant_gid'},
$::FORM{'request_gid'})");
# Populate the list of inclusions/exclusions for this flag type.
foreach my $category_type ("inclusions", "exclusions") {
@ -267,6 +280,7 @@ sub update {
validateIsRequestable();
validateIsRequesteeble();
validateAllowMultiple();
validateGroups();
my $name = SqlQuote($::FORM{'name'});
my $description = SqlQuote($::FORM{'description'});
@ -282,7 +296,9 @@ sub update {
is_active = $::FORM{'is_active'} ,
is_requestable = $::FORM{'is_requestable'} ,
is_requesteeble = $::FORM{'is_requesteeble'} ,
is_multiplicable = $::FORM{'is_multiplicable'}
is_multiplicable = $::FORM{'is_multiplicable'} ,
grant_group_id = $::FORM{'grant_gid'} ,
request_group_id = $::FORM{'request_gid'}
WHERE id = $::FORM{'id'}");
# Update the list of inclusions/exclusions for this flag type.
@ -499,3 +515,16 @@ sub validateAllowMultiple {
$::FORM{'is_multiplicable'} = $::FORM{'is_multiplicable'} ? 1 : 0;
}
sub validateGroups {
# Convert group names to group IDs
foreach my $col ("grant_gid", "request_gid") {
my $name = $::FORM{$col};
$::FORM{$col} ||= "NULL";
next if (!$name);
SendSQL("SELECT id FROM groups WHERE name = " . SqlQuote($name));
$::FORM{$col} = FetchOneColumn();
if (!$::FORM{$col}) {
ThrowUserError("group_unknown", { name => $name });
}
}
}

Просмотреть файл

@ -317,12 +317,20 @@ if ($action eq 'del') {
$hasproduct = 1;
}
my $hasflags = 0;
SendSQL("SELECT id FROM flagtypes
WHERE grant_group_id = $gid OR request_group_id = $gid");
if (FetchOneColumn()) {
$hasflags = 1;
}
$vars->{'gid'} = $gid;
$vars->{'name'} = $name;
$vars->{'description'} = $desc;
$vars->{'hasusers'} = $hasusers;
$vars->{'hasbugs'} = $hasbugs;
$vars->{'hasproduct'} = $hasproduct;
$vars->{'hasflags'} = $hasflags;
$vars->{'buglist'} = $buglist;
print Bugzilla->cgi->header();
@ -365,8 +373,19 @@ if ($action eq 'delete') {
$cantdelete = 1;
}
}
SendSQL("SELECT id FROM flagtypes
WHERE grant_group_id = $gid OR request_group_id = $gid");
if (FetchOneColumn()) {
if (!defined $cgi->param('removeflags')) {
$cantdelete = 1;
}
}
if (!$cantdelete) {
SendSQL("UPDATE flagtypes SET grant_group_id = NULL
WHERE grant_group_id = $gid");
SendSQL("UPDATE flagtypes SET request_group_id = NULL
WHERE request_group_id = $gid");
SendSQL("DELETE FROM user_group_map WHERE group_id = $gid");
SendSQL("DELETE FROM group_group_map WHERE grantor_id = $gid");
SendSQL("DELETE FROM bug_group_map WHERE group_id = $gid");

Просмотреть файл

@ -187,6 +187,25 @@
</td>
</tr>
<tr>
<th>Grant Group:</th>
<td>
the group allowed to grant/deny flags of this type
(to allow all users to grant/deny these flags, leave this empty)<br>
<input type="text" name="grant_gid" value="[% type.grant_gid FILTER html %]" size="50" maxlength="255">
</td>
</tr>
<tr>
<th>Request Group:</th>
<td>
if flags of this type are requestable, the group allowed to request them
(to allow all users to request these flags, leave this empty)<br>
Note that the request group alone has no effect if the grant group is not defined!<br>
<input type="text" name="request_gid" value="[% type.request_gid FILTER html %]" size="50" maxlength="255">
</td>
</tr>
<tr>
<th></th>
<td>

Просмотреть файл

@ -29,6 +29,7 @@
# hasusers: boolean int. True if the group includes users in it.
# hasbugs: boolean int. True if the group includes bugs in it.
# hasproduct: boolean int. True if the group is binded to a product.
# hasflags: boolean int. True if the group is used by a flag type.
# buglist: string. The list of bugs included in this group.
#%]
@ -81,11 +82,20 @@
<br><input type="checkbox" name="unbind">Delete this group anyway,
and make the <U>[% name FILTER html %]</U> publicly visible.</p>
[% END %]
[% IF hasflags %]
<p><b>This group restricts who can make changes to flags of certain types.
You cannot delete this group while there are flag types using it.</b>
<br><a href="editflagtypes.cgi?action=list&group=[% gid FILTER html %]">Show
me which types</a> - <input type="checkbox" name="removeflags">Remove all
flag types from this group for me.</p>
[% END %]
<h2>Confirmation</h2>
<p>Do you really want to delete this group?</p>
[% IF (hasusers || hasbugs || hasproduct) %]
[% IF (hasusers || hasbugs || hasproduct || hasflags) %]
<p><b>You must check all of the above boxes or correct the
indicated problems first before you can proceed.</b></p>
[% END %]

Просмотреть файл

@ -344,6 +344,17 @@
[% title = "Flag Type Name Invalid" %]
The name <em>[% name FILTER html %]</em> must be 1-50 characters long.
[% ELSIF error == "flag_update_denied" %]
[% title = "Flag Modification Denied" %]
You tried to [% IF status == "+" %] grant [% ELSIF status == "-" %] deny
[% ELSIF status == "X" %] clear [% ELSE %] request [% END %]
<code>[% name FILTER html %]</code>
[% IF status == "?" && old_status != "X" %], but this flag is already
set[% END %].
Only a sufficiently empowered user [% IF status == "X" %] or the user who
set <code>[% name FILTER html %][% old_status FILTER html %]</code> in
the first place [% END %] can make this change.
[% ELSIF error == "format_not_found" %]
[% title = "Format Not Found" %]
The requested format <em>[% format FILTER html %]</em> does not exist with
@ -362,6 +373,11 @@
[% title = "Group not specified" %]
No group was specified.
[% ELSIF error == "group_unknown" %]
[% title = "Unknown Group" %]
The group [% name FILTER html %] does not exist. Please specify
a valid group name. Create it first if necessary!
[% ELSIF error == "illegal_at_least_x_votes" %]
[% title = "Your Search Makes No Sense" %]
The <em>At least ___ votes</em> field must be a simple number.