Add separate "Create products" permission

classes
Vitaliy Filippov 2015-10-26 13:37:14 +03:00
parent f39407bcab
commit 9be26744ed
8 changed files with 95 additions and 41 deletions

View File

@ -94,6 +94,7 @@ use constant SYSTEM_GROUPS => (
{ name => 'editusers' },
{ name => 'creategroups' },
{ name => 'editclassifications' },
{ name => 'createproducts' },
{ name => 'editcomponents' },
{ name => 'editkeywords' },
{ name => 'editbugs', userregexp => '.*' },
@ -111,7 +112,7 @@ use constant SYSTEM_GROUPS => (
{
name => 'admin_index',
include => [
qw(tweakparams editusers editclassifications editcomponents creategroups
qw(tweakparams editusers editclassifications createproducts editcomponents creategroups
editfields editflagtypes editkeywords bz_canusewhines bz_editcheckers)
],
},
@ -162,22 +163,33 @@ sub update_settings
sub update_system_groups
{
my $dbh = Bugzilla->dbh;
foreach my $definition (SYSTEM_GROUPS)
{
my $exists = new Bugzilla::Group({ name => $definition->{name} });
my $grp = new Bugzilla::Group({ name => $definition->{name} });
$definition->{isbuggroup} = 0;
$definition->{description} = html_strip(Bugzilla->messages->{system_groups}->{$definition->{name}});
my $include = delete $definition->{include};
if (!$exists)
if (!$grp)
{
Bugzilla::Group->create($definition);
if ($include && @$include)
$grp = Bugzilla::Group->create($definition);
}
elsif ($definition->{name} ne 'admin_index')
{
# Always fix inclusions in admin_index
$include = undef;
}
if ($include && @$include)
{
my $cur = { map { $_ => 1 } @{$dbh->selectcol_arrayref(
'SELECT g.name FROM group_group_map gm, groups g'.
' WHERE g.id=gm.member_id AND gm.grantor_id=? AND gm.grant_type=0', undef, $grp->id
) || []} };
$include = [ grep { !$cur->{$_} } @$include ];
if (@$include)
{
$dbh->do(
'INSERT INTO group_group_map (member_id, grantor_id, grant_type)'.
' SELECT g.id, ai.id, 0 FROM groups ai, groups g WHERE ai.name=?'.
' AND g.name IN (\''.join("','", @$include).'\')', undef, $definition->{name}
' SELECT g.id, ?, 0 FROM groups g WHERE g.name IN (\''.join("','", @$include).'\')', undef, $grp->id
);
}
}

View File

@ -219,6 +219,7 @@ $Bugzilla::messages->{en} = {
tweakparams => 'Allows to <a href="editparams.cgi">change Parameters</a>.',
editusers => 'Allows to <a href="editusers.cgi">edit or disable users</a> and include/exclude them from <b>all</b> groups.',
creategroups => 'Allows to <a href="editgroups.cgi">create, destroy and edit groups</a>.',
createproducts => 'Allows to <a href="editproducts.cgi">create new products</a>.',
editclassifications => 'Allows to <a href="editclassifications.cgi">create, destroy and edit classifications</a>.',
editcomponents => 'Allows to <a href="editproducts.cgi">create, destroy and edit all products, components, versions and milestones</a>.',
editkeywords => 'Allows to <a href="editvalues.cgi?field=keywords">create, destroy and edit keywords</a>.',

View File

@ -609,15 +609,19 @@ use constant is_default => 0;
sub _create_bug_group
{
my $self = shift;
my ($create_admin_group) = @_;
my $dbh = Bugzilla->dbh;
my $group_name = $self->name;
my $group_name = ($create_admin_group ? 'admin-' : '') . $self->name;
my $i = 1;
while (new Bugzilla::Group({ name => $group_name }))
{
$group_name = $self->name . ($i++);
$group_name = ($create_admin_group ? 'admin-' : '') . $self->name . ($i++);
}
my $group_description = get_text('bug_group_description', { product => $self });
my $group_description = get_text(
$create_admin_group ? 'admin_group_description' : 'bug_group_description',
{ product => $self }
);
my $group = Bugzilla::Group->create({
name => $group_name,
@ -627,8 +631,15 @@ sub _create_bug_group
# Associate the new group and new product.
$dbh->do(
'INSERT INTO group_control_map (group_id, product_id, membercontrol, othercontrol)'.
' VALUES (?, ?, ?, ?)', undef, $group->id, $self->id, CONTROLMAPDEFAULT, CONTROLMAPNA
'INSERT INTO group_control_map (group_id, product_id, membercontrol, othercontrol, editcomponents)'.
' VALUES (?, ?, ?, ?, ?)', undef, $group->id, $self->id,
($create_admin_group ? (0, 0, 1) : (CONTROLMAPMANDATORY, CONTROLMAPMANDATORY, 0))
);
# Grant current user permission to edit the new group and include him in it
$dbh->do(
'INSERT INTO user_group_map (user_id, group_id, isbless, grant_type) VALUES (?, ?, ?, ?), (?, ?, ?, ?)',
undef, Bugzilla->user->id, $group->id, 1, 0, Bugzilla->user->id, $group->id, 0, 0
);
}

View File

@ -653,17 +653,16 @@ sub get_products_by_permission
sub get_editable_products
{
my ($self, $classification_id) = @_;
my $sql = "SELECT DISTINCT products.id FROM products";
my $t = "WHERE";
my $sql = "SELECT DISTINCT p.id FROM products p";
if (!$self->in_group('editcomponents'))
{
$sql .= ", group_control_map WHERE editcomponents=1 AND group_id IN (".$self->groups_as_string.")";
$t = "AND";
$sql .= " INNER JOIN group_control_map gm ON gm.product_id=p.id".
" AND gm.editcomponents=1 AND gm.group_id IN (".$self->groups_as_string.")";
}
if ($classification_id)
{
# restrict product list by classification
$sql .= " $t classification_id=".int($classification_id);
$sql .= " WHERE classification_id=".int($classification_id);
}
return Bugzilla::Product->new_from_list(Bugzilla->dbh->selectcol_arrayref($sql) || []);
}
@ -971,7 +970,7 @@ sub check_can_admin_product
# 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))
$self->in_group('editcomponents', $product->id)
|| $self->in_group('editcomponents')
|| ThrowUserError('product_admin_denied', {product => $product->name});

View File

@ -1,10 +1,25 @@
== UNRELEASED: beta ==
== branch: i18n ==
UI improvements:
* Separate localisation layer - now it's possible to translate Bugzilla UI
without copying templates!
== UNRELEASED: beta ==
Backports from original Bugzilla:
* WebServices from Bugzilla 5.0.1 (everything except tags).
Other new features:
* Separate "createproducts" role (group) that only allows to create new products,
but not to edit the existing ones.
Bugfixes:
* Whining now works again.
== 2015.09: 2015-09-18, commit dc07c69094f616d1eb3e523181283dcdbca0499e ==
UI improvements:

View File

@ -50,6 +50,7 @@ my $vars = {};
$vars->{doc_section} = 'products.html';
$user->in_group('editcomponents') ||
$user->in_group('createproducts') ||
scalar(@{$user->get_editable_products}) ||
ThrowUserError('auth_failure', {
group => 'editcomponents',
@ -71,12 +72,12 @@ my $useclassification = Bugzilla->get_field('classification')->enabled;
# classifications enabled)
#
if ($useclassification && !$classification_name && !$product_name)
if (!$action && $useclassification && !$classification_name && !$product_name)
{
my $class;
if ($user->in_group('editcomponents'))
{
$class = [Bugzilla::Classification->get_all];
$class = [ Bugzilla::Classification->get_all ];
}
else
{
@ -84,7 +85,7 @@ if ($useclassification && !$classification_name && !$product_name)
# which you can administer.
my $products = $user->get_editable_products;
my %class_ids = map { $_->classification_id => 1 } @$products;
$class = Bugzilla::Classification->new_from_list([keys %class_ids]);
$class = Bugzilla::Classification->new_from_list([ keys %class_ids ]);
}
$vars->{classifications} = $class;
@ -130,18 +131,17 @@ 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',
});
# The user must have the createproducts or global editcomponents privs to add new products.
$user->in_group('editcomponents') ||
$user->in_group('createproducts') ||
ThrowUserError('auth_failure', {
group => 'editcomponents',
action => 'add',
object => 'products',
});
if ($useclassification)
{
my $classification = Bugzilla::Classification->check($classification_name);
$vars->{classification} = $classification;
$vars->{classification} = $classification_name ? Bugzilla::Classification->new($classification_name) : undef;
$vars->{classifications} = [ Bugzilla::Classification->get_all ];
}
$vars->{token} = issue_session_token('add_product');
@ -159,13 +159,14 @@ 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',
});
# The user must have the createproducts or global editcomponents privs to add new products.
$user->in_group('editcomponents') ||
$user->in_group('createproducts') ||
ThrowUserError('auth_failure', {
group => 'editcomponents',
action => 'add',
object => 'products',
});
check_token_data($token, 'add_product');
@ -190,6 +191,13 @@ if ($action eq 'new')
}
my $product = Bugzilla::Product->create(\%create_params);
if (!$user->in_group('editcomponents'))
{
# User has no global editcomponents permission, so grant 'createproducts'
# group the right to manage his newly created product
$product->_create_bug_group(1);
}
# Create groups and series for the new product, if requested.
$product->_create_bug_group() if $ARGS->{makeproductgroup};
$product->_create_series() if $ARGS->{createseries};

View File

@ -51,7 +51,7 @@
]
%]
[% IF user.in_group('editcomponents') %]
[% IF user.in_group('editcomponents') || user.in_group('createproducts') %]
[% columns.push({
heading => "Action..."
content => "Add product"
@ -64,6 +64,10 @@
data = classifications
%]
[% IF user.in_group('createproducts') && !user.in_group('editcomponents') %]
<p><a href="editproducts.cgi?action=add">Add product</a></p>
[% END %]
[%# No need for the standard edit products footer, as we have an 'add'
link in the table %]

View File

@ -251,6 +251,10 @@
Access to [% terms.bugs %] in the [% product.name | html %] product
[% END %]
[% BLOCK msg_admin_group_description %]
Administration of the [% product.name | html %] product
[% END %]
[% BLOCK msg_buglist_adding_field %]
[% title = "Adding field to search page..." %]
[% link = "Click here if the page does not redisplay automatically." %]