зеркало из https://github.com/mozilla/pjs.git
Bug 189627: Implement per-product privileges - Patch by Fr��d��ric Buclin <LpSolit@gmail.com> r=mkanat a=myk
This commit is contained in:
Родитель
d9947d42db
Коммит
b0bc08db57
|
@ -609,19 +609,22 @@ sub validate_content_type {
|
|||
|
||||
=pod
|
||||
|
||||
=item C<validate_can_edit()>
|
||||
=item C<validate_can_edit($attachment, $product_id)>
|
||||
|
||||
Description: validates if the user is allowed to view and edit the attachment.
|
||||
Only the submitter or someone with editbugs privs can edit it.
|
||||
Only the submitter and users in the insider group can view
|
||||
private attachments.
|
||||
|
||||
Params: $attachment - the attachment object being edited.
|
||||
$product_id - the product ID the attachment belongs to.
|
||||
|
||||
Returns: 1 on success. Else an error is thrown.
|
||||
|
||||
=cut
|
||||
|
||||
sub validate_can_edit {
|
||||
my $attachment = shift;
|
||||
my ($attachment, $product_id) = @_;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $user = Bugzilla->user;
|
||||
|
||||
|
@ -634,27 +637,27 @@ sub validate_can_edit {
|
|||
}
|
||||
|
||||
# Users with editbugs privs can edit all attachments.
|
||||
return if $user->in_group('editbugs');
|
||||
return if $user->in_group('editbugs', $product_id);
|
||||
|
||||
# If we come here, then this attachment cannot be seen by the user.
|
||||
ThrowUserError('illegal_attachment_edit', { attach_id => $attachment->id });
|
||||
}
|
||||
|
||||
=item C<validate_obsolete($bug_id)>
|
||||
=item C<validate_obsolete($bug)>
|
||||
|
||||
Description: validates if attachments the user wants to mark as obsolete
|
||||
really belong to the given bug and are not already obsolete.
|
||||
Moreover, a user cannot mark an attachment as obsolete if
|
||||
he cannot view it (due to restrictions on it).
|
||||
|
||||
Params: $bug_id - The bug ID obsolete attachments should belong to.
|
||||
Params: $bug - The bug object obsolete attachments should belong to.
|
||||
|
||||
Returns: 1 on success. Else an error is thrown.
|
||||
|
||||
=cut
|
||||
|
||||
sub validate_obsolete {
|
||||
my ($class, $bug_id) = @_;
|
||||
my ($class, $bug) = @_;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
|
||||
# Make sure the attachment id is valid and the user has permissions to view
|
||||
|
@ -674,12 +677,12 @@ sub validate_obsolete {
|
|||
ThrowUserError('invalid_attach_id', $vars) unless $attachment;
|
||||
|
||||
# Check that the user can view and edit this attachment.
|
||||
$attachment->validate_can_edit;
|
||||
$attachment->validate_can_edit($bug->product_id);
|
||||
|
||||
$vars->{'description'} = $attachment->description;
|
||||
|
||||
if ($attachment->bug_id != $bug_id) {
|
||||
$vars->{'my_bug_id'} = $bug_id;
|
||||
if ($attachment->bug_id != $bug->bug_id) {
|
||||
$vars->{'my_bug_id'} = $bug->bug_id;
|
||||
$vars->{'attach_bug_id'} = $attachment->bug_id;
|
||||
ThrowCodeError('mismatched_bug_ids_on_obsolete', $vars);
|
||||
}
|
||||
|
@ -758,7 +761,7 @@ sub insert_attachment_for_bug {
|
|||
# Check attachments the user tries to mark as obsolete.
|
||||
my @obsolete_attachments;
|
||||
if ($cgi->param('obsolete')) {
|
||||
@obsolete_attachments = $class->validate_obsolete($bug->bug_id);
|
||||
@obsolete_attachments = $class->validate_obsolete($bug);
|
||||
}
|
||||
|
||||
# The order of these function calls is important, as Flag::validate
|
||||
|
|
|
@ -121,7 +121,6 @@ sub VALIDATORS {
|
|||
commentprivacy => \&_check_commentprivacy,
|
||||
deadline => \&_check_deadline,
|
||||
estimated_time => \&_check_estimated_time,
|
||||
keywords => \&_check_keywords,
|
||||
op_sys => \&_check_op_sys,
|
||||
priority => \&_check_priority,
|
||||
product => \&_check_product,
|
||||
|
@ -354,6 +353,8 @@ sub run_create_validators {
|
|||
|
||||
$params->{version} = $class->_check_version($product, $params->{version});
|
||||
|
||||
$params->{keywords} = $class->_check_keywords($product, $params->{keywords});
|
||||
|
||||
$params->{groups} = $class->_check_groups($product,
|
||||
$params->{groups});
|
||||
|
||||
|
@ -381,7 +382,7 @@ sub run_create_validators {
|
|||
$params->{assigned_to}, $params->{qa_contact});
|
||||
|
||||
($params->{dependson}, $params->{blocked}) =
|
||||
$class->_check_dependencies($params->{dependson}, $params->{blocked});
|
||||
$class->_check_dependencies($product, $params->{dependson}, $params->{blocked});
|
||||
|
||||
# You can't set these fields on bug creation (or sometimes ever).
|
||||
delete $params->{resolution};
|
||||
|
@ -480,7 +481,7 @@ sub _check_assigned_to {
|
|||
$name = trim($name);
|
||||
# Default assignee is the component owner.
|
||||
my $id;
|
||||
if (!$user->in_group("editbugs") || !$name) {
|
||||
if (!$user->in_group('editbugs', $component->product_id) || !$name) {
|
||||
$id = $component->default_assignee->id;
|
||||
} else {
|
||||
$id = login_to_id($name, THROW_ERROR);
|
||||
|
@ -508,7 +509,8 @@ sub _check_bug_status {
|
|||
|
||||
my @valid_statuses = VALID_ENTRY_STATUS;
|
||||
|
||||
if ($user->in_group('editbugs') || $user->in_group('canconfirm')) {
|
||||
if ($user->in_group('editbugs', $product->id)
|
||||
|| $user->in_group('canconfirm', $product->id)) {
|
||||
# Default to NEW if the user with privs hasn't selected another status.
|
||||
$status ||= 'NEW';
|
||||
}
|
||||
|
@ -599,10 +601,10 @@ sub _check_deadline {
|
|||
# Takes two comma/space-separated strings and returns arrayrefs
|
||||
# of valid bug IDs.
|
||||
sub _check_dependencies {
|
||||
my ($invocant, $depends_on, $blocks) = @_;
|
||||
my ($invocant, $product, $depends_on, $blocks) = @_;
|
||||
|
||||
# Only editbugs users can set dependencies on bug entry.
|
||||
return ([], []) unless Bugzilla->user->in_group('editbugs');
|
||||
return ([], []) unless Bugzilla->user->in_group('editbugs', $product->id);
|
||||
|
||||
$depends_on ||= '';
|
||||
$blocks ||= '';
|
||||
|
@ -676,9 +678,10 @@ sub _check_groups {
|
|||
}
|
||||
|
||||
sub _check_keywords {
|
||||
my ($invocant, $keyword_string) = @_;
|
||||
my ($invocant, $product, $keyword_string) = @_;
|
||||
$keyword_string = trim($keyword_string);
|
||||
return [] if (!$keyword_string || !Bugzilla->user->in_group('editbugs'));
|
||||
return [] if (!$keyword_string
|
||||
|| !Bugzilla->user->in_group('editbugs', $product->id));
|
||||
|
||||
my %keywords;
|
||||
foreach my $keyword (split(/[\s,]+/, $keyword_string)) {
|
||||
|
@ -801,7 +804,7 @@ sub _check_qa_contact {
|
|||
$name = trim($name);
|
||||
|
||||
my $id;
|
||||
if (!$user->in_group("editbugs") || !$name) {
|
||||
if (!$user->in_group('editbugs', $component->product_id) || !$name) {
|
||||
# We want to insert NULL into the database if we get a 0.
|
||||
$id = $component->default_qa_contact->id || undef;
|
||||
} else {
|
||||
|
@ -1207,14 +1210,16 @@ sub user {
|
|||
my $user = Bugzilla->user;
|
||||
my $canmove = Bugzilla->params->{'move-enabled'} && $user->is_mover;
|
||||
|
||||
my $unknown_privileges = $user->in_group("editbugs");
|
||||
my $prod_id = $self->{'product_id'};
|
||||
|
||||
my $unknown_privileges = $user->in_group('editbugs', $prod_id);
|
||||
my $canedit = $unknown_privileges
|
||||
|| $user->id == $self->{assigned_to_id}
|
||||
|| (Bugzilla->params->{'useqacontact'}
|
||||
&& $self->{'qa_contact_id'}
|
||||
&& $user->id == $self->{qa_contact_id});
|
||||
my $canconfirm = $unknown_privileges
|
||||
|| $user->in_group("canconfirm");
|
||||
|| $user->in_group('canconfirm', $prod_id);
|
||||
my $isreporter = $user->id
|
||||
&& $user->id == $self->{reporter_id};
|
||||
|
||||
|
@ -1824,19 +1829,19 @@ sub check_can_change_field {
|
|||
# $PrivilegesRequired = 2 : the assignee or an empowered user;
|
||||
# $PrivilegesRequired = 3 : an empowered user.
|
||||
|
||||
# Allow anyone with "editbugs" privs to change anything.
|
||||
if ($user->in_group('editbugs')) {
|
||||
# Allow anyone with (product-specific) "editbugs" privs to change anything.
|
||||
if ($user->in_group('editbugs', $self->{'product_id'})) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# *Only* users with "canconfirm" privs can confirm bugs.
|
||||
# *Only* users with (product-specific) "canconfirm" privs can confirm bugs.
|
||||
if ($field eq 'canconfirm'
|
||||
|| ($field eq 'bug_status'
|
||||
&& $oldvalue eq 'UNCONFIRMED'
|
||||
&& is_open_state($newvalue)))
|
||||
{
|
||||
$$PrivilegesRequired = 3;
|
||||
return $user->in_group('canconfirm');
|
||||
return $user->in_group('canconfirm', $self->{'product_id'});
|
||||
}
|
||||
|
||||
# Make sure that a valid bug ID has been given.
|
||||
|
|
|
@ -171,6 +171,15 @@ sub initial_cc {
|
|||
return $self->{'initial_cc'};
|
||||
}
|
||||
|
||||
sub product {
|
||||
my $self = shift;
|
||||
if (!defined $self->{'product'}) {
|
||||
require Bugzilla::Product; # We cannot |use| it.
|
||||
$self->{'product'} = new Bugzilla::Product($self->product_id);
|
||||
}
|
||||
return $self->{'product'};
|
||||
}
|
||||
|
||||
###############################
|
||||
#### Accessors ####
|
||||
###############################
|
||||
|
@ -229,7 +238,8 @@ Bugzilla::Component - Bugzilla product component class.
|
|||
my $product_id = $component->product_id;
|
||||
my $default_assignee = $component->default_assignee;
|
||||
my $default_qa_contact = $component->default_qa_contact;
|
||||
my $initial_cc = $component->initial_cc
|
||||
my $initial_cc = $component->initial_cc;
|
||||
my $product = $component->product;
|
||||
my $bug_flag_types = $component->flag_types->{'bug'};
|
||||
my $attach_flag_types = $component->flag_types->{'attachment'};
|
||||
|
||||
|
@ -305,6 +315,14 @@ Initial CC List.
|
|||
|
||||
Returns: Two references to an array of flagtype objects.
|
||||
|
||||
=item C<product()>
|
||||
|
||||
Description: Returns the product the component belongs to.
|
||||
|
||||
Params: none.
|
||||
|
||||
Returns: A Bugzilla::Product object.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SUBROUTINES
|
||||
|
|
|
@ -101,6 +101,7 @@ use File::Basename;
|
|||
FULLTEXT_BUGLIST_LIMIT
|
||||
|
||||
ADMIN_GROUP_NAME
|
||||
PER_PRODUCT_PRIVILEGES
|
||||
|
||||
SENDMAIL_EXE
|
||||
SENDMAIL_PATH
|
||||
|
@ -289,6 +290,9 @@ use constant FULLTEXT_BUGLIST_LIMIT => 200;
|
|||
# Default administration group name.
|
||||
use constant ADMIN_GROUP_NAME => 'admin';
|
||||
|
||||
# Privileges which can be per-product.
|
||||
use constant PER_PRODUCT_PRIVILEGES => ('editcomponents', 'editbugs', 'canconfirm');
|
||||
|
||||
# Path to sendmail.exe (Windows only)
|
||||
use constant SENDMAIL_EXE => '/usr/lib/sendmail.exe';
|
||||
# Paths to search for the sendmail binary (non-Windows)
|
||||
|
|
|
@ -777,6 +777,12 @@ use constant ABSTRACT_SCHEMA => {
|
|||
membercontrol => {TYPE => 'BOOLEAN', NOTNULL => 1},
|
||||
othercontrol => {TYPE => 'BOOLEAN', NOTNULL => 1},
|
||||
canedit => {TYPE => 'BOOLEAN', NOTNULL => 1},
|
||||
editcomponents => {TYPE => 'BOOLEAN', NOTNULL => 1,
|
||||
DEFAULT => 'FALSE'},
|
||||
editbugs => {TYPE => 'BOOLEAN', NOTNULL => 1,
|
||||
DEFAULT => 'FALSE'},
|
||||
canconfirm => {TYPE => 'BOOLEAN', NOTNULL => 1,
|
||||
DEFAULT => 'FALSE'},
|
||||
],
|
||||
INDEXES => [
|
||||
group_control_map_product_id_idx =>
|
||||
|
|
|
@ -501,6 +501,14 @@ sub update_table_definitions {
|
|||
$dbh->bz_alter_column('longdescs', 'thetext',
|
||||
{ TYPE => 'MEDIUMTEXT', NOTNULL => 1 }, '');
|
||||
|
||||
# 2006-10-20 LpSolit@gmail.com - Bug 189627
|
||||
$dbh->bz_add_column('group_control_map', 'editcomponents',
|
||||
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
|
||||
$dbh->bz_add_column('group_control_map', 'editbugs',
|
||||
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
|
||||
$dbh->bz_add_column('group_control_map', 'canconfirm',
|
||||
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
|
||||
|
||||
################################################################
|
||||
# New --TABLE-- changes should go *** A B O V E *** this point #
|
||||
################################################################
|
||||
|
|
|
@ -85,7 +85,10 @@ sub group_controls {
|
|||
group_control_map.entry,
|
||||
group_control_map.membercontrol,
|
||||
group_control_map.othercontrol,
|
||||
group_control_map.canedit
|
||||
group_control_map.canedit,
|
||||
group_control_map.editcomponents,
|
||||
group_control_map.editbugs,
|
||||
group_control_map.canconfirm
|
||||
FROM groups
|
||||
LEFT JOIN group_control_map
|
||||
ON groups.id = group_control_map.group_id
|
||||
|
|
|
@ -482,8 +482,32 @@ sub bless_groups {
|
|||
}
|
||||
|
||||
sub in_group {
|
||||
my ($self, $group) = @_;
|
||||
return exists $self->groups->{$group} ? 1 : 0;
|
||||
my ($self, $group, $product_id) = @_;
|
||||
if (exists $self->groups->{$group}) {
|
||||
return 1;
|
||||
}
|
||||
elsif ($product_id && detaint_natural($product_id)) {
|
||||
# Make sure $group exists on a per-product basis.
|
||||
return 0 unless (grep {$_ eq $group} PER_PRODUCT_PRIVILEGES);
|
||||
|
||||
$self->{"product_$product_id"} = {} unless exists $self->{"product_$product_id"};
|
||||
if (!defined $self->{"product_$product_id"}->{$group}) {
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $in_group = $dbh->selectrow_array(
|
||||
"SELECT 1
|
||||
FROM group_control_map
|
||||
WHERE product_id = ?
|
||||
AND $group != 0
|
||||
AND group_id IN (" . $self->groups_as_string . ") " .
|
||||
$dbh->sql_limit(1),
|
||||
undef, $product_id);
|
||||
|
||||
$self->{"product_$product_id"}->{$group} = $in_group ? 1 : 0;
|
||||
}
|
||||
return $self->{"product_$product_id"}->{$group};
|
||||
}
|
||||
# If we come here, then the user is not in the requested group.
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub in_group_id {
|
||||
|
@ -492,6 +516,26 @@ sub in_group_id {
|
|||
return exists $j{$id} ? 1 : 0;
|
||||
}
|
||||
|
||||
sub get_products_by_permission {
|
||||
my ($self, $group) = @_;
|
||||
# Make sure $group exists on a per-product basis.
|
||||
return [] unless (grep {$_ eq $group} PER_PRODUCT_PRIVILEGES);
|
||||
|
||||
my $product_ids = Bugzilla->dbh->selectcol_arrayref(
|
||||
"SELECT DISTINCT product_id
|
||||
FROM group_control_map
|
||||
WHERE $group != 0
|
||||
AND group_id IN(" . $self->groups_as_string . ")");
|
||||
|
||||
# No need to go further if the user has no "special" privs.
|
||||
return [] unless scalar(@$product_ids);
|
||||
|
||||
# We will restrict the list to products the user can see.
|
||||
my $selectable_products = $self->get_selectable_products;
|
||||
my @products = grep {lsearch($product_ids, $_->id) > -1} @$selectable_products;
|
||||
return \@products;
|
||||
}
|
||||
|
||||
sub can_see_user {
|
||||
my ($self, $otherUser) = @_;
|
||||
my $query;
|
||||
|
@ -667,15 +711,15 @@ sub can_enter_product {
|
|||
}
|
||||
# It could be closed for bug entry...
|
||||
elsif ($product->disallow_new) {
|
||||
ThrowUserError('product_disabled', {product => $product->name});
|
||||
ThrowUserError('product_disabled', {product => $product});
|
||||
}
|
||||
# It could have no components...
|
||||
elsif (!@{$product->components}) {
|
||||
ThrowUserError('missing_component', {product => $product->name});
|
||||
ThrowUserError('missing_component', {product => $product});
|
||||
}
|
||||
# It could have no versions...
|
||||
elsif (!@{$product->versions}) {
|
||||
ThrowUserError ('missing_version', {product => $product->name});
|
||||
ThrowUserError ('missing_version', {product => $product});
|
||||
}
|
||||
|
||||
die "can_enter_product reached an unreachable location.";
|
||||
|
@ -726,6 +770,20 @@ sub get_accessible_products {
|
|||
return [ values %products ];
|
||||
}
|
||||
|
||||
sub check_can_admin_product {
|
||||
my ($self, $product_name) = @_;
|
||||
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
($self->in_group('editcomponents', $product->id)
|
||||
&& $self->can_see_product($product->name))
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
|
||||
# Return the validated product object.
|
||||
return $product;
|
||||
}
|
||||
|
||||
sub can_request_flag {
|
||||
my ($self, $flag_type) = @_;
|
||||
|
||||
|
@ -861,23 +919,23 @@ sub derive_regexp_groups {
|
|||
|
||||
sub product_responsibilities {
|
||||
my $self = shift;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
return $self->{'product_resp'} if defined $self->{'product_resp'};
|
||||
return [] unless $self->id;
|
||||
|
||||
my $h = Bugzilla->dbh->selectall_arrayref(
|
||||
qq{SELECT products.name AS productname,
|
||||
components.name AS componentname,
|
||||
initialowner,
|
||||
initialqacontact
|
||||
FROM products, components
|
||||
WHERE products.id = components.product_id
|
||||
AND ? IN (initialowner, initialqacontact)
|
||||
},
|
||||
{'Slice' => {}}, $self->id);
|
||||
$self->{'product_resp'} = $h;
|
||||
my $comp_ids = $dbh->selectcol_arrayref('SELECT id FROM components
|
||||
WHERE initialowner = ?
|
||||
OR initialqacontact = ?',
|
||||
undef, ($self->id, $self->id));
|
||||
|
||||
return $h;
|
||||
# We cannot |use| it, because Component.pm already |use|s User.pm.
|
||||
require Bugzilla::Component;
|
||||
my @components;
|
||||
push(@components, new Bugzilla::Component($_)) foreach (@$comp_ids);
|
||||
|
||||
$self->{'product_resp'} = \@components;
|
||||
return $self->{'product_resp'};
|
||||
}
|
||||
|
||||
sub can_bless {
|
||||
|
@ -1797,9 +1855,11 @@ Returns a string containing a comma-separated list of numeric group ids. If
|
|||
the user is not a member of any groups, returns "-1". This is most often used
|
||||
within an SQL IN() function.
|
||||
|
||||
=item C<in_group>
|
||||
=item C<in_group($group_name, $product_id)>
|
||||
|
||||
Determines whether or not a user is in the given group by name.
|
||||
Determines whether or not a user is in the given group by name.
|
||||
If $product_id is given, it also checks for local privileges for
|
||||
this product.
|
||||
|
||||
=item C<in_group_id>
|
||||
|
||||
|
@ -1814,6 +1874,12 @@ The arrayref consists of the groups the user can bless, taking into account
|
|||
that having editusers permissions means that you can bless all groups, and
|
||||
that you need to be aware of a group in order to bless a group.
|
||||
|
||||
=item C<get_products_by_permission($group)>
|
||||
|
||||
Returns a list of product objects for which the user has $group privileges
|
||||
and which he can access.
|
||||
$group must be one of the groups defined in PER_PRODUCT_PRIVILEGES.
|
||||
|
||||
=item C<can_see_user(user)>
|
||||
|
||||
Returns 1 if the specified user account exists and is visible to the user,
|
||||
|
@ -1888,6 +1954,14 @@ method should be called in such a case to force reresolution of these groups.
|
|||
|
||||
Returns: an array of product objects.
|
||||
|
||||
=item C<check_can_admin_product($product_name)>
|
||||
|
||||
Description: Checks whether the user is allowed to administrate the product.
|
||||
|
||||
Params: $product_name - a product name.
|
||||
|
||||
Returns: On success, a product object. On failure, an error is thrown.
|
||||
|
||||
=item C<can_request_flag($flag_type)>
|
||||
|
||||
Description: Checks whether the user can request flags of the given type.
|
||||
|
@ -1937,29 +2011,8 @@ list).
|
|||
|
||||
=item C<product_responsibilities>
|
||||
|
||||
Retrieve user's product responsibilities as a list of hashes.
|
||||
One hash per Bugzilla component the user has a responsibility for.
|
||||
These are the hash keys:
|
||||
|
||||
=over
|
||||
|
||||
=item productname
|
||||
|
||||
Name of the product.
|
||||
|
||||
=item componentname
|
||||
|
||||
Name of the component.
|
||||
|
||||
=item initialowner
|
||||
|
||||
User ID of default assignee.
|
||||
|
||||
=item initialqacontact
|
||||
|
||||
User ID of default QA contact.
|
||||
|
||||
=back
|
||||
Retrieve user's product responsibilities as a list of component objects.
|
||||
Each object is a component the user has a responsibility for.
|
||||
|
||||
=item C<can_bless>
|
||||
|
||||
|
|
|
@ -416,12 +416,14 @@ sub enter
|
|||
ValidateBugID($bugid);
|
||||
validateCanChangeBug($bugid);
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
my $user = Bugzilla->user;
|
||||
|
||||
my $bug = new Bugzilla::Bug($bugid, $user->id);
|
||||
# Retrieve the attachments the user can edit from the database and write
|
||||
# them into an array of hashes where each hash represents one attachment.
|
||||
my $canEdit = "";
|
||||
if (!Bugzilla->user->in_group("editbugs")) {
|
||||
$canEdit = "AND submitter_id = " . Bugzilla->user->id;
|
||||
if (!$user->in_group('editbugs', $bug->product_id)) {
|
||||
$canEdit = "AND submitter_id = " . $user->id;
|
||||
}
|
||||
my $attachments = $dbh->selectall_arrayref(
|
||||
"SELECT attach_id AS id, description, isprivate
|
||||
|
@ -430,24 +432,13 @@ sub enter
|
|||
AND isobsolete = 0 $canEdit
|
||||
ORDER BY attach_id",{'Slice' =>{}}, $bugid);
|
||||
|
||||
# Retrieve the bug summary (for displaying on screen) and assignee.
|
||||
my ($bugsummary, $assignee_id) = $dbh->selectrow_array(
|
||||
"SELECT short_desc, assigned_to FROM bugs
|
||||
WHERE bug_id = ?", undef, $bugid);
|
||||
|
||||
# Define the variables and functions that will be passed to the UI template.
|
||||
$vars->{'bugid'} = $bugid;
|
||||
$vars->{'bug'} = $bug;
|
||||
$vars->{'attachments'} = $attachments;
|
||||
$vars->{'bugassignee_id'} = $assignee_id;
|
||||
$vars->{'bugsummary'} = $bugsummary;
|
||||
|
||||
my ($product_id, $component_id)= $dbh->selectrow_array(
|
||||
"SELECT product_id, component_id FROM bugs
|
||||
WHERE bug_id = ?", undef, $bugid);
|
||||
|
||||
my $flag_types = Bugzilla::FlagType::match({'target_type' => 'attachment',
|
||||
'product_id' => $product_id,
|
||||
'component_id' => $component_id});
|
||||
'product_id' => $bug->product_id,
|
||||
'component_id' => $bug->component_id});
|
||||
$vars->{'flag_types'} = $flag_types;
|
||||
$vars->{'any_flags_requesteeble'} = grep($_->is_requesteeble, @$flag_types);
|
||||
|
||||
|
@ -487,7 +478,7 @@ sub insert
|
|||
# Assign the bug to the user, if they are allowed to take it
|
||||
my $owner = "";
|
||||
|
||||
if ($cgi->param('takebug') && Bugzilla->user->in_group("editbugs")) {
|
||||
if ($cgi->param('takebug') && $user->in_group('editbugs', $bug->product_id)) {
|
||||
|
||||
my @fields = ("assigned_to", "bug_status", "resolution", "everconfirmed",
|
||||
"login_name");
|
||||
|
@ -606,8 +597,9 @@ sub update
|
|||
# Retrieve and validate parameters
|
||||
ValidateComment(scalar $cgi->param('comment'));
|
||||
my ($attach_id, $bugid) = validateID();
|
||||
my $bug = new Bugzilla::Bug($bugid);
|
||||
my $attachment = Bugzilla::Attachment->get($attach_id);
|
||||
$attachment->validate_can_edit;
|
||||
$attachment->validate_can_edit($bug->product_id);
|
||||
validateCanChangeAttachment($attach_id);
|
||||
Bugzilla::Attachment->validate_description(THROW_ERROR);
|
||||
Bugzilla::Attachment->validate_is_patch(THROW_ERROR);
|
||||
|
@ -636,7 +628,6 @@ sub update
|
|||
});
|
||||
Bugzilla::Flag::validate($cgi, $bugid, $attach_id);
|
||||
|
||||
my $bug = new Bugzilla::Bug($bugid);
|
||||
# Lock database tables in preparation for updating the attachment.
|
||||
$dbh->bz_lock_tables('attachments WRITE', 'flags WRITE' ,
|
||||
'flagtypes READ', 'fielddefs READ', 'bugs_activity WRITE',
|
||||
|
@ -784,7 +775,6 @@ sub delete_attachment {
|
|||
# Make sure the administrator is allowed to edit this attachment.
|
||||
my ($attach_id, $bug_id) = validateID();
|
||||
my $attachment = Bugzilla::Attachment->get($attach_id);
|
||||
$attachment->validate_can_edit;
|
||||
validateCanChangeAttachment($attach_id);
|
||||
|
||||
$attachment->datasize || ThrowUserError('attachment_removed');
|
||||
|
|
|
@ -36,7 +36,6 @@ use Bugzilla::Series;
|
|||
use Bugzilla::Util;
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::User;
|
||||
use Bugzilla::Product;
|
||||
use Bugzilla::Component;
|
||||
use Bugzilla::Bug;
|
||||
use Bugzilla::Token;
|
||||
|
@ -76,6 +75,7 @@ my $whoid = $user->id;
|
|||
print $cgi->header();
|
||||
|
||||
$user->in_group('editcomponents')
|
||||
|| scalar(@{$user->get_products_by_permission('editcomponents')})
|
||||
|| ThrowUserError("auth_failure", {group => "editcomponents",
|
||||
action => "edit",
|
||||
object => "components"});
|
||||
|
@ -94,7 +94,13 @@ my $token = $cgi->param('token');
|
|||
#
|
||||
|
||||
unless ($product_name) {
|
||||
$vars->{'products'} = $user->get_selectable_products;
|
||||
my $selectable_products = $user->get_selectable_products;
|
||||
# If the user has editcomponents privs for some products only,
|
||||
# we have to restrict the list of products to display.
|
||||
unless ($user->in_group('editcomponents')) {
|
||||
$selectable_products = $user->get_products_by_permission('editcomponents');
|
||||
}
|
||||
$vars->{'products'} = $selectable_products;
|
||||
$vars->{'showbugcounts'} = $showbugcounts;
|
||||
|
||||
$template->process("admin/components/select-product.html.tmpl", $vars)
|
||||
|
@ -102,13 +108,7 @@ unless ($product_name) {
|
|||
exit;
|
||||
}
|
||||
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
|
||||
#
|
||||
# action='' -> Show nice list of components
|
||||
|
|
|
@ -23,7 +23,6 @@ use Bugzilla;
|
|||
use Bugzilla::Constants;
|
||||
use Bugzilla::Util;
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::Product;
|
||||
use Bugzilla::Milestone;
|
||||
use Bugzilla::Bug;
|
||||
use Bugzilla::Token;
|
||||
|
@ -43,6 +42,7 @@ my $whoid = $user->id;
|
|||
print $cgi->header();
|
||||
|
||||
$user->in_group('editcomponents')
|
||||
|| scalar(@{$user->get_products_by_permission('editcomponents')})
|
||||
|| ThrowUserError("auth_failure", {group => "editcomponents",
|
||||
action => "edit",
|
||||
object => "milestones"});
|
||||
|
@ -62,7 +62,13 @@ my $token = $cgi->param('token');
|
|||
#
|
||||
|
||||
unless ($product_name) {
|
||||
$vars->{'products'} = $user->get_selectable_products;
|
||||
my $selectable_products = $user->get_selectable_products;
|
||||
# If the user has editcomponents privs for some products only,
|
||||
# we have to restrict the list of products to display.
|
||||
unless ($user->in_group('editcomponents')) {
|
||||
$selectable_products = $user->get_products_by_permission('editcomponents');
|
||||
}
|
||||
$vars->{'products'} = $selectable_products;
|
||||
$vars->{'showbugcounts'} = $showbugcounts;
|
||||
|
||||
$template->process("admin/milestones/select-product.html.tmpl", $vars)
|
||||
|
@ -70,13 +76,7 @@ unless ($product_name) {
|
|||
exit;
|
||||
}
|
||||
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
|
||||
#
|
||||
# action='' -> Show nice list of milestones
|
||||
|
|
|
@ -64,6 +64,7 @@ my $vars = {};
|
|||
print $cgi->header();
|
||||
|
||||
$user->in_group('editcomponents')
|
||||
|| scalar(@{$user->get_products_by_permission('editcomponents')})
|
||||
|| ThrowUserError("auth_failure", {group => "editcomponents",
|
||||
action => "edit",
|
||||
object => "products"});
|
||||
|
@ -100,10 +101,11 @@ if (Bugzilla->params->{'useclassification'}
|
|||
#
|
||||
|
||||
if (!$action && !$product_name) {
|
||||
my $classification;
|
||||
my $products;
|
||||
|
||||
if (Bugzilla->params->{'useclassification'}) {
|
||||
my $classification =
|
||||
$classification =
|
||||
Bugzilla::Classification::check_classification($classification_name);
|
||||
|
||||
$products = $user->get_selectable_products($classification->id);
|
||||
|
@ -112,6 +114,14 @@ if (!$action && !$product_name) {
|
|||
$products = $user->get_selectable_products;
|
||||
}
|
||||
|
||||
# If the user has editcomponents privs for some products only,
|
||||
# we have to restrict the list of products to display.
|
||||
unless ($user->in_group('editcomponents')) {
|
||||
$products = $user->get_products_by_permission('editcomponents');
|
||||
if (Bugzilla->params->{'useclassification'}) {
|
||||
@$products = grep {$_->classification_id == $classification->id} @$products;
|
||||
}
|
||||
}
|
||||
$vars->{'products'} = $products;
|
||||
$vars->{'showbugcounts'} = $showbugcounts;
|
||||
|
||||
|
@ -130,6 +140,13 @@ if (!$action && !$product_name) {
|
|||
#
|
||||
|
||||
if ($action eq 'add') {
|
||||
# The user must have the global editcomponents privs to add
|
||||
# new products.
|
||||
$user->in_group('editcomponents')
|
||||
|| ThrowUserError("auth_failure", {group => "editcomponents",
|
||||
action => "add",
|
||||
object => "products"});
|
||||
|
||||
if (Bugzilla->params->{'useclassification'}) {
|
||||
my $classification =
|
||||
Bugzilla::Classification::check_classification($classification_name);
|
||||
|
@ -149,6 +166,13 @@ if ($action eq 'add') {
|
|||
#
|
||||
|
||||
if ($action eq 'new') {
|
||||
# The user must have the global editcomponents privs to add
|
||||
# new products.
|
||||
$user->in_group('editcomponents')
|
||||
|| ThrowUserError("auth_failure", {group => "editcomponents",
|
||||
action => "add",
|
||||
object => "products"});
|
||||
|
||||
check_token_data($token, 'add_product');
|
||||
# Cleanups and validity checks
|
||||
|
||||
|
@ -325,12 +349,7 @@ if ($action eq 'new') {
|
|||
#
|
||||
|
||||
if ($action eq 'del') {
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
|
||||
if (Bugzilla->params->{'useclassification'}) {
|
||||
my $classification =
|
||||
|
@ -356,14 +375,9 @@ if ($action eq 'del') {
|
|||
#
|
||||
|
||||
if ($action eq 'delete') {
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
check_token_data($token, 'delete_product');
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
|
||||
$vars->{'product'} = $product;
|
||||
|
||||
if (Bugzilla->params->{'useclassification'}) {
|
||||
|
@ -435,12 +449,7 @@ if ($action eq 'delete') {
|
|||
#
|
||||
|
||||
if ($action eq 'edit' || (!$action && $product_name)) {
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
|
||||
if (Bugzilla->params->{'useclassification'}) {
|
||||
my $classification;
|
||||
|
@ -490,13 +499,8 @@ if ($action eq 'edit' || (!$action && $product_name)) {
|
|||
#
|
||||
|
||||
if ($action eq 'updategroupcontrols') {
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
check_token_data($token, 'edit_group_controls');
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
|
||||
my @now_na = ();
|
||||
my @now_mandatory = ();
|
||||
|
@ -584,19 +588,23 @@ if ($action eq 'updategroupcontrols') {
|
|||
|
||||
my $sth_Insert = $dbh->prepare('INSERT INTO group_control_map
|
||||
(group_id, product_id, entry, membercontrol,
|
||||
othercontrol, canedit)
|
||||
VALUES (?, ?, ?, ?, ?, ?)');
|
||||
othercontrol, canedit, editcomponents,
|
||||
canconfirm, editbugs)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
|
||||
my $sth_Update = $dbh->prepare('UPDATE group_control_map
|
||||
SET entry = ?, membercontrol = ?,
|
||||
othercontrol = ?, canedit = ?
|
||||
othercontrol = ?, canedit = ?,
|
||||
editcomponents = ?, canconfirm = ?,
|
||||
editbugs = ?
|
||||
WHERE group_id = ? AND product_id = ?');
|
||||
|
||||
my $sth_Delete = $dbh->prepare('DELETE FROM group_control_map
|
||||
WHERE group_id = ? AND product_id = ?');
|
||||
|
||||
$groups = $dbh->selectall_arrayref('SELECT id, name, entry, membercontrol,
|
||||
othercontrol, canedit
|
||||
othercontrol, canedit,
|
||||
editcomponents, canconfirm, editbugs
|
||||
FROM groups
|
||||
LEFT JOIN group_control_map
|
||||
ON group_control_map.group_id = id
|
||||
|
@ -606,35 +614,60 @@ if ($action eq 'updategroupcontrols') {
|
|||
undef, $product->id);
|
||||
|
||||
foreach my $group (@$groups) {
|
||||
my ($groupid, $groupname, $entry, $membercontrol,
|
||||
$othercontrol, $canedit) = @$group;
|
||||
my ($groupid, $groupname, $entry, $membercontrol, $othercontrol,
|
||||
$canedit, $editcomponents, $canconfirm, $editbugs) = @$group;
|
||||
my $newentry = $cgi->param("entry_$groupid") || 0;
|
||||
my $newmembercontrol = $cgi->param("membercontrol_$groupid") || 0;
|
||||
my $newothercontrol = $cgi->param("othercontrol_$groupid") || 0;
|
||||
my $newcanedit = $cgi->param("canedit_$groupid") || 0;
|
||||
my $new_editcomponents = $cgi->param("editcomponents_$groupid") || 0;
|
||||
my $new_canconfirm = $cgi->param("canconfirm_$groupid") || 0;
|
||||
my $new_editbugs = $cgi->param("editbugs_$groupid") || 0;
|
||||
|
||||
my $oldentry = $entry;
|
||||
$entry = $entry || 0;
|
||||
$membercontrol = $membercontrol || 0;
|
||||
$othercontrol = $othercontrol || 0;
|
||||
$canedit = $canedit || 0;
|
||||
# Set undefined values to 0.
|
||||
$entry ||= 0;
|
||||
$membercontrol ||= 0;
|
||||
$othercontrol ||= 0;
|
||||
$canedit ||= 0;
|
||||
$editcomponents ||= 0;
|
||||
$canconfirm ||= 0;
|
||||
$editbugs ||= 0;
|
||||
|
||||
# We use them in placeholders only. So it's safe to detaint them.
|
||||
detaint_natural($newentry);
|
||||
detaint_natural($newothercontrol);
|
||||
detaint_natural($newmembercontrol);
|
||||
detaint_natural($newcanedit);
|
||||
if ((!defined($oldentry)) &&
|
||||
(($newentry) || ($newmembercontrol) || ($newcanedit))) {
|
||||
detaint_natural($new_editcomponents);
|
||||
detaint_natural($new_canconfirm);
|
||||
detaint_natural($new_editbugs);
|
||||
|
||||
if (!defined($oldentry)
|
||||
&& ($newentry || $newmembercontrol || $newcanedit
|
||||
|| $new_editcomponents || $new_canconfirm || $new_editbugs))
|
||||
{
|
||||
$sth_Insert->execute($groupid, $product->id, $newentry,
|
||||
$newmembercontrol, $newothercontrol, $newcanedit);
|
||||
} elsif (($newentry != $entry)
|
||||
|| ($newmembercontrol != $membercontrol)
|
||||
|| ($newothercontrol != $othercontrol)
|
||||
|| ($newcanedit != $canedit)) {
|
||||
$newmembercontrol, $newothercontrol, $newcanedit,
|
||||
$new_editcomponents, $new_canconfirm, $new_editbugs);
|
||||
}
|
||||
elsif (($newentry != $entry)
|
||||
|| ($newmembercontrol != $membercontrol)
|
||||
|| ($newothercontrol != $othercontrol)
|
||||
|| ($newcanedit != $canedit)
|
||||
|| ($new_editcomponents != $editcomponents)
|
||||
|| ($new_canconfirm != $canconfirm)
|
||||
|| ($new_editbugs != $editbugs))
|
||||
{
|
||||
$sth_Update->execute($newentry, $newmembercontrol, $newothercontrol,
|
||||
$newcanedit, $groupid, $product->id);
|
||||
$newcanedit, $new_editcomponents, $new_canconfirm,
|
||||
$new_editbugs, $groupid, $product->id);
|
||||
}
|
||||
|
||||
if (($newentry == 0) && ($newmembercontrol == 0)
|
||||
&& ($newothercontrol == 0) && ($newcanedit == 0)) {
|
||||
if (!$newentry && !$newmembercontrol && !$newothercontrol
|
||||
&& !$newcanedit && !$new_editcomponents && !$new_canconfirm
|
||||
&& !$new_editbugs)
|
||||
{
|
||||
$sth_Delete->execute($groupid, $product->id);
|
||||
}
|
||||
}
|
||||
|
@ -759,12 +792,7 @@ if ($action eq 'update') {
|
|||
|
||||
my $checkvotes = 0;
|
||||
|
||||
# First make sure the product name is valid.
|
||||
my $product_old = Bugzilla::Product::check_product($product_old_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product_old->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product_old->name});
|
||||
my $product_old = $user->check_can_admin_product($product_old_name);
|
||||
|
||||
if (Bugzilla->params->{'useclassification'}) {
|
||||
my $classification;
|
||||
|
@ -1005,16 +1033,12 @@ if ($action eq 'update') {
|
|||
#
|
||||
|
||||
if ($action eq 'editgroupcontrols') {
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
|
||||
# Display a group if it is either enabled or has bugs for this product.
|
||||
my $groups = $dbh->selectall_arrayref(
|
||||
'SELECT id, name, entry, membercontrol, othercontrol, canedit,
|
||||
editcomponents, editbugs, canconfirm,
|
||||
isactive, COUNT(bugs.bug_id) AS bugcount
|
||||
FROM groups
|
||||
LEFT JOIN group_control_map
|
||||
|
@ -1028,7 +1052,8 @@ if ($action eq 'editgroupcontrols') {
|
|||
WHERE isbuggroup != 0
|
||||
AND (isactive != 0 OR entry IS NOT NULL OR bugs.bug_id IS NOT NULL) ' .
|
||||
$dbh->sql_group_by('name', 'id, entry, membercontrol,
|
||||
othercontrol, canedit, isactive'),
|
||||
othercontrol, canedit, isactive,
|
||||
editcomponents, canconfirm, editbugs'),
|
||||
{'Slice' => {}}, ($product->id, $product->id));
|
||||
|
||||
$vars->{'product'} = $product;
|
||||
|
|
|
@ -364,7 +364,6 @@ if ($action eq 'search') {
|
|||
action => "delete",
|
||||
object => "users"});
|
||||
$vars->{'otheruser'} = $otherUser;
|
||||
$vars->{'editcomponents'} = Bugzilla->user->in_group('editcomponents');
|
||||
|
||||
# Find other cross references.
|
||||
$vars->{'assignee_or_qa'} = $dbh->selectrow_array(
|
||||
|
|
|
@ -35,7 +35,6 @@ use Bugzilla;
|
|||
use Bugzilla::Constants;
|
||||
use Bugzilla::Util;
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::Product;
|
||||
use Bugzilla::Version;
|
||||
use Bugzilla::Token;
|
||||
|
||||
|
@ -53,6 +52,7 @@ my $user = Bugzilla->login(LOGIN_REQUIRED);
|
|||
print $cgi->header();
|
||||
|
||||
$user->in_group('editcomponents')
|
||||
|| scalar(@{$user->get_products_by_permission('editcomponents')})
|
||||
|| ThrowUserError("auth_failure", {group => "editcomponents",
|
||||
action => "edit",
|
||||
object => "versions"});
|
||||
|
@ -71,7 +71,13 @@ my $token = $cgi->param('token');
|
|||
#
|
||||
|
||||
unless ($product_name) {
|
||||
$vars->{'products'} = $user->get_selectable_products;
|
||||
my $selectable_products = $user->get_selectable_products;
|
||||
# If the user has editcomponents privs for some products only,
|
||||
# we have to restrict the list of products to display.
|
||||
unless ($user->in_group('editcomponents')) {
|
||||
$selectable_products = $user->get_products_by_permission('editcomponents');
|
||||
}
|
||||
$vars->{'products'} = $selectable_products;
|
||||
$vars->{'showbugcounts'} = $showbugcounts;
|
||||
|
||||
$template->process("admin/versions/select-product.html.tmpl", $vars)
|
||||
|
@ -79,13 +85,7 @@ unless ($product_name) {
|
|||
exit;
|
||||
}
|
||||
|
||||
# First make sure the product name is valid.
|
||||
my $product = Bugzilla::Product::check_product($product_name);
|
||||
|
||||
# Then make sure the user is allowed to edit properties of this product.
|
||||
$user->can_see_product($product->name)
|
||||
|| ThrowUserError('product_access_denied', {product => $product->name});
|
||||
|
||||
my $product = $user->check_can_admin_product($product_name);
|
||||
|
||||
#
|
||||
# action='' -> Show nice list of versions
|
||||
|
|
|
@ -300,6 +300,9 @@ sub pickos {
|
|||
# End of subroutines
|
||||
##############################################################################
|
||||
|
||||
my $has_editbugs = $user->in_group('editbugs', $product->id);
|
||||
my $has_canconfirm = $user->in_group('canconfirm', $product->id);
|
||||
|
||||
# If a user is trying to clone a bug
|
||||
# Check that the user has authorization to view the parent bug
|
||||
# Create an instance of Bug that holds the info from the parent
|
||||
|
@ -327,11 +330,11 @@ $vars->{'op_sys'} = get_legal_field_values('op_sys');
|
|||
$vars->{'use_keywords'} = 1 if Bugzilla::Keyword::keyword_count();
|
||||
|
||||
$vars->{'assigned_to'} = formvalue('assigned_to');
|
||||
$vars->{'assigned_to_disabled'} = !Bugzilla->user->in_group('editbugs');
|
||||
$vars->{'assigned_to_disabled'} = !$has_editbugs;
|
||||
$vars->{'cc_disabled'} = 0;
|
||||
|
||||
$vars->{'qa_contact'} = formvalue('qa_contact');
|
||||
$vars->{'qa_contact_disabled'} = !Bugzilla->user->in_group('editbugs');
|
||||
$vars->{'qa_contact_disabled'} = !$has_editbugs;
|
||||
|
||||
$vars->{'cloned_bug_id'} = $cloned_bug_id;
|
||||
|
||||
|
@ -465,7 +468,7 @@ if ( Bugzilla->params->{'usetargetmilestone'} ) {
|
|||
# to let them mark bugs as ASSIGNED)
|
||||
|
||||
my @status;
|
||||
if ($user->in_group('editbugs') || $user->in_group('canconfirm')) {
|
||||
if ($has_editbugs || $has_canconfirm) {
|
||||
@status = ('NEW', 'ASSIGNED');
|
||||
}
|
||||
elsif (!$product->votes_to_confirm) {
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
[% IF has_bits.size %]
|
||||
You have the following permission [% terms.bits %] set on your account:
|
||||
<p>
|
||||
<br>
|
||||
<table align="center">
|
||||
[% FOREACH bit_description = has_bits %]
|
||||
<tr>
|
||||
|
@ -47,6 +46,23 @@
|
|||
</tr>
|
||||
[% END %]
|
||||
</table>
|
||||
|
||||
[% FOREACH privs = ["editcomponents", "canconfirm", "editbugs"] %]
|
||||
[% SET products = ${"local_$privs"} %]
|
||||
[% IF products && products.size %]
|
||||
<br>
|
||||
<p>
|
||||
You also have local '[% privs FILTER html %]' privileges
|
||||
for the following products:
|
||||
</p>
|
||||
<p>
|
||||
[% FOREACH product = products %]
|
||||
[% product.name FILTER html %]<br>
|
||||
[% END %]
|
||||
</p>
|
||||
[% END %]
|
||||
[% END %]
|
||||
|
||||
[% ELSE %]
|
||||
There are no permission [% terms.bits %] set on your account.
|
||||
[% END %]
|
||||
|
|
|
@ -112,6 +112,9 @@ versions:</a>
|
|||
[% g.othercontrol FILTER html %]
|
||||
[% IF g.entry %], ENTRY[% END %]
|
||||
[% IF g.canedit %], CANEDIT[% END %]
|
||||
[% IF g.editcomponents %], editcomponents[% END %]
|
||||
[% IF g.canconfirm %], canconfirm[% END %]
|
||||
[% IF g.editbugs %], editbugs[% END %]
|
||||
[% ELSE %]
|
||||
DISABLED
|
||||
[% END %]
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
<hr>
|
||||
|
||||
[% UNLESS no_add_product_link %]
|
||||
[% UNLESS no_add_product_link || !user.in_group("editcomponents") %]
|
||||
<a title="Add a product"
|
||||
href="editproducts.cgi?action=add">Add</a> a product[% -%]
|
||||
[%# Strictly speaking, we should not have to check for a
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
<th>MemberControl</th>
|
||||
<th>OtherControl</th>
|
||||
<th>Canedit</th>
|
||||
<th>editcomponents</th>
|
||||
<th>canconfirm</th>
|
||||
<th>editbugs</th>
|
||||
<th>[% terms.Bugs %]</th>
|
||||
</tr>
|
||||
[% FOREACH group = groups %]
|
||||
|
@ -50,7 +53,7 @@
|
|||
<td>
|
||||
[% group.name FILTER html %]
|
||||
</td>
|
||||
<td align="center" colspan=4>
|
||||
<td align="center" colspan=7>
|
||||
Disabled
|
||||
</td>
|
||||
<td>
|
||||
|
@ -118,6 +121,18 @@
|
|||
<input type=checkbox value=1 name=canedit_[% group.id %]
|
||||
[% " checked=\"checked\"" IF group.canedit %]>
|
||||
</td>
|
||||
<td>
|
||||
<input type=checkbox value=1 name=editcomponents_[% group.id %]
|
||||
[% " checked=\"checked\"" IF group.editcomponents %]>
|
||||
</td>
|
||||
<td>
|
||||
<input type=checkbox value=1 name=canconfirm_[% group.id %]
|
||||
[% " checked=\"checked\"" IF group.canconfirm %]>
|
||||
</td>
|
||||
<td>
|
||||
<input type=checkbox value=1 name=editbugs_[% group.id %]
|
||||
[% " checked=\"checked\"" IF group.editbugs %]>
|
||||
</td>
|
||||
<td>
|
||||
[% group.bugcount %]
|
||||
</td>
|
||||
|
@ -146,6 +161,21 @@ the groups with Canedit selected. ONLY users who are members of
|
|||
all the canedit groups will be able to edit. This is an additional
|
||||
restriction that further restricts what can be edited by a user.
|
||||
<p>
|
||||
The following settings control let you choose privileges on a <b>per-product basis</b>.
|
||||
This is a convenient way to give privileges to some users for some products
|
||||
only, without having to give them global privileges which would affect all
|
||||
products:
|
||||
<p>
|
||||
Any group having <b>editcomponents</b> selected allows users who are
|
||||
in this group to edit all aspects of this product, including components,
|
||||
milestones and versions.
|
||||
<p>
|
||||
Any group having <b>canconfirm</b> selected allows users who are
|
||||
in this group to confirm [% terms.bugs %] in this product.
|
||||
<p>
|
||||
Any group having <b>editbugs</b> selected allows users who are
|
||||
in this group to edit all fields of [% terms.bugs %] in this product.
|
||||
<p>
|
||||
The <b>MemberControl</b> and <b>OtherControl</b> fields
|
||||
indicate which [% terms.bugs %] will be placed in
|
||||
this group according to the following definitions.
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
# listselectionvalues: selection values to recreate the current user
|
||||
# list.
|
||||
# editusers: is viewing user member of editusers?
|
||||
# editcomponents: is viewing user member of editcomponents?
|
||||
# otheruser: Bugzilla::User object of the viewed user.
|
||||
# reporter: number of bugs reported by the user
|
||||
# assignee_or_qa: number of bugs the user is either the assignee
|
||||
|
@ -57,8 +56,8 @@
|
|||
%]
|
||||
|
||||
[% responsibilityterms = {
|
||||
'initialowner' => 'Default Assignee',
|
||||
'initialqacontact' => 'Default QA Contact'
|
||||
'default_assignee' => 'Default Assignee',
|
||||
'default_qa_contact' => 'Default QA Contact'
|
||||
}
|
||||
%]
|
||||
|
||||
|
@ -93,21 +92,21 @@
|
|||
[% FOREACH component = otheruser.product_responsibilities %]
|
||||
<li>
|
||||
[% andstring = '' %]
|
||||
[% FOREACH responsibility = ['initialowner', 'initialqacontact'] %]
|
||||
[% IF component.$responsibility == otheruser.id %]
|
||||
[% FOREACH responsibility = ['default_assignee', 'default_qa_contact'] %]
|
||||
[% IF component.${responsibility}.id == otheruser.id %]
|
||||
[% andstring %] [% responsibilityterms.$responsibility %]
|
||||
[% andstring = ' and ' %]
|
||||
[% END %]
|
||||
[% END %]
|
||||
for
|
||||
[% IF editcomponents %]
|
||||
[% IF user.in_group("editcomponents", component.product_id) %]
|
||||
<a href="editcomponents.cgi?action=edit&product=
|
||||
[% component.productname FILTER url_quote %]&component=
|
||||
[% component.componentname FILTER url_quote %]">
|
||||
[% component.product.name FILTER url_quote %]&component=
|
||||
[% component.name FILTER url_quote %]">
|
||||
[% END %]
|
||||
[%+ component.productname FILTER html %]:
|
||||
[% component.componentname FILTER html %]
|
||||
[% IF editcomponents %]
|
||||
[%+ component.product.name FILTER html %]:
|
||||
[% component.name FILTER html %]
|
||||
[% IF user.in_group("editcomponents", component.product_id) %]
|
||||
</a>
|
||||
[% END %]
|
||||
</li>
|
||||
|
@ -125,7 +124,7 @@
|
|||
one product.
|
||||
</p>
|
||||
<p>
|
||||
[% IF editcomponents %]
|
||||
[% IF user.in_group("editcomponents", component.product_id) %]
|
||||
Change this by clicking the product editing links above,
|
||||
[% ELSE %]
|
||||
For now, you can
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[%# Define strings that will serve as the title and header of this page %]
|
||||
[% title = BLOCK %]Create New Attachment for [% terms.Bug %] #[% bugid %][% END %]
|
||||
[% title = BLOCK %]Create New Attachment for [% terms.Bug %] #[% bug.bug_id %][% END %]
|
||||
[% header = BLOCK %]Create New Attachment for
|
||||
[%+ "$terms.Bug $bugid" FILTER bug_link(bugid) FILTER none %][% END %]
|
||||
[% subheader = BLOCK %][% bugsummary FILTER html %][% END %]
|
||||
[%+ "$terms.Bug $bug.bug_id" FILTER bug_link(bug.bug_id) FILTER none %][% END %]
|
||||
[% subheader = BLOCK %][% bug.short_desc FILTER html %][% END %]
|
||||
|
||||
[% PROCESS global/header.html.tmpl
|
||||
title = title
|
||||
|
@ -40,7 +40,7 @@
|
|||
%]
|
||||
|
||||
<form name="entryform" method="post" action="attachment.cgi" enctype="multipart/form-data">
|
||||
<input type="hidden" name="bugid" value="[% bugid %]">
|
||||
<input type="hidden" name="bugid" value="[% bug.bug_id %]">
|
||||
<input type="hidden" name="action" value="insert">
|
||||
|
||||
<table class="attachment_entry">
|
||||
|
@ -66,7 +66,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
[% IF (user.id != bugassignee_id) AND user.groups.editbugs %]
|
||||
[% IF (user.id != bug.assigned_to.id) AND user.in_group("editbugs", bug.product_id) %]
|
||||
<tr>
|
||||
<th>Reassignment:</th>
|
||||
<td>
|
||||
|
|
|
@ -476,7 +476,7 @@ function handleWantsAttachment(wants_attachment) {
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
[% IF user.in_group('editbugs') %]
|
||||
[% IF user.in_group('editbugs', product.id) %]
|
||||
[% IF use_keywords %]
|
||||
<tr>
|
||||
<td align="right" valign="top">
|
||||
|
|
|
@ -424,7 +424,7 @@
|
|||
],
|
||||
|
||||
'attachment/create.html.tmpl' => [
|
||||
'bugid',
|
||||
'bug.bug_id',
|
||||
'attachment.id',
|
||||
],
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@
|
|||
href="editparams.cgi">' IF user.groups.tweakparams %]
|
||||
[% '<link rel="Administration" title="Users"
|
||||
href="editusers.cgi">' IF user.groups.editusers %]
|
||||
[% '<link rel="Administration" title="Products"
|
||||
href="editproducts.cgi">' IF user.groups.editcomponents %]
|
||||
[% '<link rel="Administration" title="Products" href="editproducts.cgi">'
|
||||
IF user.groups.editcomponents || user.get_products_by_permission("editcomponents").size %]
|
||||
[% '<link rel="Administration" title="Flag Types"
|
||||
href="editflagtypes.cgi">' IF user.groups.editcomponents %]
|
||||
[% '<link rel="Administration" title="Groups"
|
||||
|
|
|
@ -58,10 +58,13 @@
|
|||
<li><span class="separator">[% sep %]</span><a href="editclassifications.cgi">Classifications</a></li>
|
||||
[% sep = "| " %]
|
||||
[% END %]
|
||||
[% IF user.groups.editcomponents %]
|
||||
[% IF user.groups.editcomponents || user.get_products_by_permission("editcomponents").size %]
|
||||
<li><span class="separator">[% sep %]</span><a href="editproducts.cgi">Products</a></li>
|
||||
[% sep = "| " %]
|
||||
[% END %]
|
||||
[% IF user.groups.editcomponents %]
|
||||
<li><span class="separator">[% sep %]</span><a href="editflagtypes.cgi">Flags</a></li>
|
||||
[% sep = "| " %]
|
||||
[% END %]
|
||||
[% IF user.groups.admin %]
|
||||
<li><span class="separator">[% sep %]</span><a href="editfields.cgi">Custom Fields</a></li>
|
||||
|
|
|
@ -917,11 +917,11 @@
|
|||
[% title = "Missing Component" %]
|
||||
[% admindocslinks = {'products.html' => 'Administering products',
|
||||
'components.html' => 'Creating a component'} %]
|
||||
Sorry, the product <em>[% product FILTER html %]</em>
|
||||
Sorry, the product <em>[% product.name FILTER html %]</em>
|
||||
has to have at least one component in order for you to
|
||||
enter [% terms.abug %] into it.<br>
|
||||
[% IF user.in_group("editcomponents") %]
|
||||
<a href="editcomponents.cgi?action=add&product=[% product FILTER url_quote %]">Create
|
||||
[% IF user.in_group("editcomponents", product.id) %]
|
||||
<a href="editcomponents.cgi?action=add&product=[% product.name FILTER url_quote %]">Create
|
||||
a new component</a>.
|
||||
[% ELSE %]
|
||||
Please contact [% Param("maintainer") %] and ask them
|
||||
|
@ -989,11 +989,11 @@
|
|||
[% ELSIF error == "missing_version" %]
|
||||
[% title = "Missing Version" %]
|
||||
[% admindocslinks = {'versions.html' => 'Defining versions'} %]
|
||||
Sorry, the product <em>[% product FILTER html %]</em>
|
||||
Sorry, the product <em>[% product.name FILTER html %]</em>
|
||||
has to have at least one version in order for you to
|
||||
enter [% terms.abug %] into it.<p>
|
||||
[% IF user.in_group("editcomponents") %]
|
||||
<a href="editversions.cgi?action=add&product=[% product FILTER url_quote %]">Create
|
||||
[% IF user.in_group("editcomponents", product.id) %]
|
||||
<a href="editversions.cgi?action=add&product=[% product.name FILTER url_quote %]">Create
|
||||
a new version</a>.
|
||||
[% ELSE %]
|
||||
Please contact [% Param("maintainer") %] and ask them
|
||||
|
@ -1213,7 +1213,7 @@
|
|||
[% title = BLOCK %]Product closed for [% terms.Bugs %] Entry[% END %]
|
||||
[% admindocslinks = {'products.html' => 'Administering products'} %]
|
||||
Sorry, entering [% terms.bugs %] into the
|
||||
product <em>[% product FILTER html %]</em> has been disabled.
|
||||
product <em>[% product.name FILTER html %]</em> has been disabled.
|
||||
|
||||
[% ELSIF error == "product_edit_denied" %]
|
||||
[% title = "Product Edit Access Denied" %]
|
||||
|
|
|
@ -369,7 +369,13 @@ sub DoPermissions {
|
|||
push(@set_bits, {"desc" => $desc, "name" => $nam});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# If the user has product specific privileges, inform him about that.
|
||||
foreach my $privs (PER_PRODUCT_PRIVILEGES) {
|
||||
next if $user->in_group($privs);
|
||||
$vars->{"local_$privs"} = $user->get_products_by_permission($privs);
|
||||
}
|
||||
|
||||
$vars->{'has_bits'} = \@has_bits;
|
||||
$vars->{'set_bits'} = \@set_bits;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче