Skip to content
Snippets Groups Projects
Commit 13fc0efa authored by Felipe Artur's avatar Felipe Artur Committed by Michael Kozono
Browse files

Let project reporters create issue from group boards

The current state of group issue boards does not show the "Add issues"
button on the UI for users that are reporters of group child projects.
parent 24de5d65
No related branches found
No related tags found
No related merge requests found
Showing
with 168 additions and 6 deletions
Loading
Loading
@@ -114,7 +114,7 @@ export default {
name="issue_title"
autocomplete="off"
/>
<project-select v-if="groupId" :group-id="groupId" />
<project-select v-if="groupId" :group-id="groupId" :list="list" />
<div class="clearfix prepend-top-10">
<gl-button
ref="submit-button"
Loading
Loading
Loading
Loading
@@ -6,6 +6,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../eventhub';
import Api from '../../api';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
 
export default {
name: 'BoardProjectSelect',
Loading
Loading
@@ -19,6 +20,10 @@ export default {
required: true,
default: 0,
},
list: {
type: Object,
required: true,
},
},
data() {
return {
Loading
Loading
@@ -49,6 +54,12 @@ export default {
selectable: true,
data: (term, callback) => {
this.loading = true;
const additionalAttrs = {};
if (this.list.type && this.list.type !== 'backlog') {
additionalAttrs.min_access_level = featureAccessLevel.EVERYONE;
}
return Api.groupProjects(
this.groupId,
term,
Loading
Loading
@@ -56,6 +67,7 @@ export default {
with_issues_enabled: true,
with_shared: false,
include_subgroups: true,
...additionalAttrs,
},
projects => {
this.loading = false;
Loading
Loading
Loading
Loading
@@ -16,7 +16,7 @@ export const visibilityLevelDescriptions = {
),
};
 
const featureAccessLevel = {
export const featureAccessLevel = {
NOT_ENABLED: 0,
PROJECT_MEMBERS: 10,
EVERYONE: 20,
Loading
Loading
Loading
Loading
@@ -10,7 +10,7 @@ module BoardsHelper
boards_endpoint: @boards_endpoint,
lists_endpoint: board_lists_path(board),
board_id: board.id,
disabled: "#{!can?(current_user, :admin_list, current_board_parent)}",
disabled: (!can?(current_user, :create_non_backlog_issues, board)).to_s,
issue_link_base: build_issue_link_base,
root_path: root_path,
bulk_update_path: @bulk_issues_path,
Loading
Loading
# frozen_string_literal: true
 
class BoardPolicy < BasePolicy
include FindGroupProjects
delegate { @subject.parent }
 
condition(:is_group_board) { @subject.group_board? }
Loading
Loading
@@ -13,4 +15,20 @@ class BoardPolicy < BasePolicy
enable :read_milestone
enable :read_issue
end
condition(:reporter_of_group_projects) do
next unless @user
group_projects_for(user: @user, group: @subject.parent)
.visible_to_user_and_access_level(@user, ::Gitlab::Access::REPORTER)
.exists?
end
rule { is_group_board & reporter_of_group_projects }.policy do
enable :create_non_backlog_issues
end
rule { is_project_board & can?(:admin_issue) }.policy do
enable :create_non_backlog_issues
end
end
# frozen_string_literal: true
module FindGroupProjects
extend ActiveSupport::Concern
def group_projects_for(user:, group:)
GroupProjectsFinder.new(
group: group,
current_user: user,
options: { include_subgroups: true, only_owned: true }
).execute
end
end
# frozen_string_literal: true
 
class GroupPolicy < BasePolicy
include FindGroupProjects
desc "Group is public"
with_options scope: :subject, score: 0
condition(:public_group) { @subject.public? }
Loading
Loading
@@ -22,7 +24,7 @@ class GroupPolicy < BasePolicy
condition(:can_change_parent_share_with_group_lock) { can?(:change_share_with_group_lock, @subject.parent) }
 
condition(:has_projects) do
GroupProjectsFinder.new(group: @subject, current_user: @user, options: { include_subgroups: true, only_owned: true }).execute.any?
group_projects_for(user: @user, group: @subject).any?
end
 
with_options scope: :subject, score: 0
Loading
Loading
---
title: Let project reporters create issue from group boards
merge_request: 29866
author:
type: fixed
Loading
Loading
@@ -156,7 +156,8 @@ Parameters:
| `with_issues_enabled` | boolean | no | Limit by projects with issues feature enabled. Default is `false` |
| `with_merge_requests_enabled` | boolean | no | Limit by projects with merge requests feature enabled. Default is `false` |
| `with_shared` | boolean | no | Include projects shared to this group. Default is `true` |
| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
| `min_access_level` | integer | no | Limit to projects where current user has at least this [access level](members.md) |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_security_reports` | boolean | no | **(ULTIMATE)** Return only projects that have security reports artifacts present in any of their builds. This means "projects with security reports enabled". Default is `false` |
 
Loading
Loading
Loading
Loading
@@ -75,6 +75,7 @@ module API
).execute
projects = projects.with_issues_available_for_user(current_user) if params[:with_issues_enabled]
projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
projects = projects.visible_to_user_and_access_level(current_user, params[:min_access_level]) if params[:min_access_level]
projects = reorder_projects(projects)
paginate(projects)
end
Loading
Loading
@@ -213,6 +214,7 @@ module API
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
optional :with_shared, type: Boolean, default: true, desc: 'Include projects shared to this group'
optional :include_subgroups, type: Boolean, default: false, desc: 'Includes projects in subgroups of this group'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user on projects'
 
use :pagination
use :with_custom_attributes
Loading
Loading
Loading
Loading
@@ -127,4 +127,44 @@ describe 'Issue Boards new issue', :js do
end
end
end
context 'group boards' do
set(:group) { create(:group, :public) }
set(:project) { create(:project, namespace: group) }
set(:group_board) { create(:board, group: group) }
set(:list) { create(:list, board: group_board, position: 0) }
context 'for unauthorized users' do
before do
sign_in(user)
visit group_board_path(group, group_board)
wait_for_requests
end
it 'displays new issue button in open list' do
expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1)
end
it 'does not display new issue button in label list' do
page.within('.board.is-draggable') do
expect(page).not_to have_selector('.issue-count-badge-add-button')
end
end
end
context 'for authorized users' do
it 'display new issue button in label list' do
project = create(:project, namespace: group)
project.add_reporter(user)
sign_in(user)
visit group_board_path(group, group_board)
wait_for_requests
page.within('.board.is-draggable') do
expect(page).to have_selector('.issue-count-badge-add-button')
end
end
end
end
end
Loading
Loading
@@ -40,7 +40,7 @@ describe BoardsHelper do
assign(:project, project)
 
allow(helper).to receive(:current_user) { user }
allow(helper).to receive(:can?).with(user, :admin_list, project).and_return(true)
allow(helper).to receive(:can?).with(user, :create_non_backlog_issues, board).and_return(true)
end
 
it 'returns a board_lists_path as lists_endpoint' do
Loading
Loading
Loading
Loading
@@ -56,4 +56,57 @@ describe BoardPolicy do
end
end
end
context 'create_non_backlog_issues' do
context 'for project boards' do
let!(:current_user) { create(:user) }
subject { described_class.new(current_user, project_board) }
context 'when user can admin project issues' do
it 'allows to add non backlog issues from issue board' do
project.add_reporter(current_user)
expect_allowed(:create_non_backlog_issues)
end
end
context 'when user cannot admin project issues' do
it 'does not allow to add non backlog issues from issue board' do
project.add_guest(current_user)
expect_disallowed(:create_non_backlog_issues)
end
end
end
context 'for group boards' do
let!(:current_user) { create(:user) }
let!(:project_1) { create(:project, namespace: group) }
let!(:project_2) { create(:project, namespace: group) }
let!(:group_board) { create(:board, group: group) }
subject { described_class.new(current_user, group_board) }
before do
project_1.add_guest(current_user)
end
context 'when user is at least reporter in one of the child projects' do
it 'allows to add non backlog issues from issue board' do
project_2.add_reporter(current_user)
expect_allowed(:create_non_backlog_issues)
end
end
context 'when user is not a reporter from any child projects' do
it 'does not allow to add non backlog issues from issue board' do
project_2.add_guest(current_user)
expect_disallowed(:create_non_backlog_issues)
end
end
end
end
end
Loading
Loading
@@ -483,6 +483,22 @@ describe API::Groups do
 
describe "GET /groups/:id/projects" do
context "when authenticated as user" do
context 'with min access level' do
it 'returns projects with min access level or higher' do
group_guest = create(:user)
group1.add_guest(group_guest)
project4 = create(:project, group: group1)
project1.add_guest(group_guest)
project3.add_reporter(group_guest)
project4.add_developer(group_guest)
get api("/groups/#{group1.id}/projects", group_guest), params: { min_access_level: Gitlab::Access::REPORTER }
project_ids = json_response.map { |proj| proj['id'] }
expect(project_ids).to match_array([project3.id, project4.id])
end
end
it "returns the group's projects" do
get api("/groups/#{group1.id}/projects", user1)
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment